Request for comments: Listing files with conflicts in `pijul status`


#1

One of the really cool features of Pijul (IMO) is a good internal representation of conflicts. But I find myself searching for conflicts after a pull by grepping for something like >>>>>> to find files with conflicts.

@lthms suggested that conflicts could be shown as part of the output of pijul status. The first draft is here.

I’m posting it here, because I’d love to get some feedback - I basically looked at how files are output in libpijul/src/graph.rs:output_file(). From my understanding conflicts are identified from the internal graph representation of files by a combination of a DFS and identifying the strongly-connected components. If I’m reading the code right, the SCCs are used to determine cyclical conflicts.

This brings me to another question: Are there more than one type of conflict? It would seem that there is a difference between cyclical and acyclical conflicts, but I’m not sure if there is any reason to present them differently to the user (just knowing which files contains conflicts might be enough).

Example

I have an example (that I want to turn into a bats test):

#!/bin/bash
set -e

REPO=conflicts
TODO=todo.txt
rm -rf $REPO

pijul init $REPO
cd $REPO

cat > $TODO <<EOF
TODO
* brush teeth
EOF

pijul add $TODO
pijul record -a -m "Initial commit"

pijul fork --branch master shower
pijul checkout shower # Just to be sure

sed -i '2i* take a shower' $TODO
pijul record -a -m "Add shower to $TODO"

pijul fork --branch master shoes
pijul checkout shoes

sed -i '2i* Put on shoes' $TODO
pijul record -a -m "Add shoes to $TODO"

# Merge branches 'shoes' and 'shower'
pijul pull -a --from-branch shower .

Now the todo.txt file contains a conflict and checkout file contains:

$ cat todo.txt
TODO
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
* Put on shoes
================================
* take a shower
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
* brush teeth

and pijul status shows

$ pijul status
On branch shoes

Unresolved conflicts:
  (fix conflicts and record the resolution with "pijul record ...")

        todo.txt

Let me know what you think! Thanks :slight_smile:


#2

Thats awesome! Thank you very much for your work. I don’t have the time right now, but I will definitely try your patch in a day or two.

Thing to consider IMO:

  1. Does the conflics goes away when pijul unrecord is called?
  2. Does the patch deals with conflicts which involve more than two patches (there were one in pijul at some point, and they are still a little hard to read and understand)
  3. Does pijul status works with changing branches?

#3

Thank you - let me know when you’ve tried it out!

  1. You mean, if you unrecord a patch that introduced a conflict? It should, yes.
  2. It doesn’t directly look at patches, it looks at the (current) internal graph representation of a file - furthermore it only looks at existing files, because the internal representation also includes files that might have been deleted (they still exist in the history)
  3. It should, yes. In fact, it only looks at the current branch, so if a conflict exists on only branch, status should only show the conflict when that branch is checked out.

#4

I haven’t had a close look yet, but this seems like a great feature. It’s very natural for status to indicate conflicted files (especially as conflict markers might get accidentally recorded).


#5

That’s what I figured - it’d be a great help to avoid “resolving” a conflict by merely committing the “flattened” conflict (as is the case right now in libpijul).

EDIT: The referenced conflict has been fixed


#6

I think I remember @pmeunier saying on IRC that such a thing cannot happen (that is, pijul refuses to record confict markers. But maybe I am wrong.

I have been quite busy lately, but I will try to have a closer look soon. Sorry for the delay.


Writing the patch description from an editor
#7

Hi! I’m finally trying to catch up on Pijul, after a tough month on many projects (including big internal changes to the Nest).

@laumann: I love this feature, I’ll try to test it and merge this week.
Also, there are indeed several kinds of conflicts, but cyclical conflicts cannot yet be produced by our current diff algorithm.

Another kind of conflict is “zombies”, where Alice deletes a block of text, while Bob inserts lines in that block.

Indeed, Pijul would refuse to record conflict markers, except it some cases where the file is heavily edited and you leave conflict markers.


#8

Thank you :blush:

Would it make sense to list the different kinds of conflicts, or is it better to just point to the file and say “here be conflicts”?


#9

I don’t know, let’s discuss it!
Our ambition with Pijul is to be as featureful as Git (with many features implemented in simpler, more efficient ways, and requiring less commands), and at the same time that people who start programming can pick it up quickly.

As such, my reasoning when I wrote that module was to group circular conflicts and unordered conflicts under the same “can’t find an order” type of conflicts. I knew about zombies, but didn’t really think about them. They might deserve their own thing: if you record a file with zombies, the zombies will get alive.

(this last sentence was a tribute to George Romero).


#10

I think it depends on how you’re supposed to deal with each type of conflict. One thing is for different types of conflicts to exist, but if the method of dealing with them is always “you see a conflict, resolve it by flattening and recording it”, then they might as well be presented as the same.

If zombies should be handled differently, then they should also be presented differently.


#11

I just merged your patch.
I only had to fix a few conflicts, and removed duplicate code between libpijul/src/output.rs and libpijul/src/graph.rs.

Thanks for your work!


#12

Oh, sweet - thanks! I wanted to remove some of the duplication, thanks for taking care of that :smile:


#13

Given how often we seem to be pushing conflicts to remote repos, I think a conflict resolution ui would be helpful here.

So, if a user would try to record or apply patches, and would introduce conflicts, start a series of interactive conflict resolution prompts. This would look similar to the interactive hunk selection ui of pijul record or darcs record also with the option of dropping into a text editor to fix the conflict if the user cannot just pick one side or the other to resolve it.

I guess this could go into the pijul conflicts command.

  • pijul conflicts could take, as arguments, remote and local branches, or, these can be the default branches your repo already knows about.
  • pijul conflicts could be invoked directly from the cli.
  • pijul conflicts would be automatically invoked from pijul record, apply/push before recording, applying, or pushing.

The workflow would be something like this:

  1. Attempt to record some patches to your repo.

If conflicts are detected:

  1. prompt to pull only the conflicting patches into your local repo.
  2. then, run the interactive conflict resolution ui.
  3. rewrite the non-recorded working copy changes that you attempted to record in step 0 with the information given in step 2 so that they don’t conflict with the patches you pulled in step 1.
  4. optionally record those non-conflicting changes on top and optionally continue with command you invoked or continue editing files at your leisure and invoke record/push/pull from the cli later.

Step 1 could be “pull the conflicting parts of the conflicting patches into your local repo” and change what you record so that it won’t conflict with those patches when you pijul push later, but I think it’s best to preserve attribution.

…currently waiting on some conflicts to be fixed before I start implementing some of this pijul stuff.


#14

@pointfree AFAIK, the current state of the repo is good. Just delete pijul/Cargo.lock and you should be fine. There is an issue with the tests also, but I think I saw @laumann has pushed a patch on his fork that fixes it.