Understanding dependencies

Hello, I haven’t used Pijul yet but it sounds interesting based on the documentation I’ve read.

My understanding is that both diffs and dependencies can be language-dependent. In addition to the minimal dependencies needed to reconstruct files and directories, there could be additional semantic dependencies. Perhaps a function call might depend on a function definition?

The details will probably be worked out some time in the future, but I’m curious about how it might work.

Suppose we write patch A, which calls a function defined in previous patch B, so we add a dependency from A to B. Then someone edits B to create B2, which is compatible. (The code compiles and runs with either definition.)

Conceptually, A may depend on either B or B2, but only the dependency on B is reified (since B2 didn’t exist). B no longer appears in the latest version since it’s been entirely replaced by B2. How would that look to users? What sort of conflicts would show up?

Also, more fundamentally, it seems like Pijul has dependencies on “buried” patches in other ways, such as using the first commit of a file to represent a file. What does that look like?

What is a dependency anyway? Is it just a unique ID or does it have to refer to a patch?

1 Like

Hi! Welcome here!

First, dependencies are always changes. Minimal dependencies are currently inferred, and you can add your own dependencies to changes when recording in text format, by adding, in the dependencies section, lines of the form:


Where ABC…DE is the hash of the dependency you want to introduce. You can’t currently add custom dependencies to changes that contain binaries.

Pijul can be seen as a filesystem, and has a notion of “inodes”, which are unique identifiers for files and directories. A change adding content at the very beginning of a file will depend on the change introducing the inode (which is the change introducing the file, as you noticed). Note that file names are stored separate from the inodes, meaning that changes inside a file commute with file moves and renames.


Makes sense. I suppose one goal of adding extra dependencies would be to find conflicts? How does that happen? I’m guessing that a conflict would happen if a depended-on node gets deleted, sort of like a foreign key constraint in SQL?

What might we do with this? One possibility would be to add dependencies from changes adding import statements to the files that were imported, so that if the file were removed, that would be a conflict. But the error message would probably be worse than you’d get by doing a compile, and depending on the inode won’t match the language semantics because if the file is renamed, the import statement would break and need to be updated. Perhaps it’s better if version control isn’t used for finding this kind of error?

That’s what I believe too, and Pijul doesn’t try to do anything like that. Dependencies are always relative to the past, they never prevent explicit operations in the future. Using extra dependencies, you can express that a module declaration depends on a file being inserted, so that when you apply the change importing the module, you must apply the change declaring it (this is a hypothetical example, since you would be more likely to do both in the same change).

Once these changes are applied, nothing prevents you in Pijul from applying other changes, for example renaming the file. The only thing you can’t do is breaking the dependency relation: you can’t unrecord a dependency of a change A without first unrecording A.

1 Like