A composable pijul user interface? (brainstorm)

I agree with you @tae, the distinction between declarative and imperative commands should be clear. Since I’ve had some time and distance from this it’s become clearer to me what’s actually needed in the ui.

The row is for source. The column is for destination. Source and destination can be: label, remote, file, or directory.

labels of hunks & filepaths (patches)

Some of these seem unnecessary but are actually useful when combined with branches, etc.

track untrack tracked untracked
track record adds revert removes apply patch to cwd clean changes not in patch
untrack record removes revert & unrecord, ignore unrecord clean changes not in patch/cwd
tracked record adds revert adds (clean) blame, log, ls diff/status: adds
untracked record removes revert files missing in patch diff/status: removes show nothing

labels of patches (branches)

track untrack tracked untracked
track sync (re)name to pull, merge put
untrack (re)name from delete-branch unpull unpull --not-in-remote
tracked push, fork unpush checkout push (dryrun)
untracked get unpush --not-in-local pull (dryrun) in-repo?

So we have hunks, (file)paths, and labels (branches). Because there are only the commands “track”, “untrack”, “tracked”, and “untracked” we could probably just make it positional and not need to type out the words “track” “untrack”. The commands “tracked” and “untracked” could be default (for read-only querying) while “track” and “untrack” arguments would be prefixed with a flag “-w”

Let’s see how this looks:

Keep in mind the arguments are arbitrary so these examples are highly redundant. -w writes something. No -w means read, query, or show something.

sync:

synchronize branch1 and branch2 so they have the same patches.

pijul -w <branch1> -w <branch2>

pull:

pull patches from remote branch to local branch.

pijul -w <branch_local> <branch_remote/other>
pijul -w <branch_remote/other> # if current branch is the destination

push:

push patches from local branch to remote branch.

pijul <branch_local> -w <branch_remote/other>
pijul -w <branch_remote/other> # if current branch is the source

unpull:

Rollback patches in <branch_local> that are not in <branch_remote> but are in <branch_local>.

pijul -w <branch_local> <branch_remote/other>

unpush:

Rollback patches in <branch_remote> that are in <branch_remote> but not in <branch_local>.

pijul <branch_local> -w <branch_remote/other>
pijul -w <branch_remote/other> # if current branch is src

rename-branch:

pijul -w <existing_branch_name> -w <non_existent_branch_name>

delete-branch:

pijul -w -w <branch_to_delete> # empty branch name implies the master, previous, or parent branch

fork:

pijul <existing_branch_name> -w <non_existent_branch_name>
pijul -w <non_existent_branch_name> # if forking from current branch

checkout:

pijul <existing_branch_name>

put:

Here we use a filepath argument for the current directory, “.”

pijul . -w <branch_remote>

get:

pijul -w . <branch_remote>

init (if not already inside a repo):

pijul -w .

add current directory to current branch of current repo:

pijul -w .

…mix and match filepath, patch hash, branch label, and hunk arguments. I got bored writing examples. Maybe I’ll do more later. Let me know if I’m being overly verbose.

I don’t think it will be too difficult to map this to the commands in the cells of the above tables with clap. We just need a prefix or something to identify arguments as label, local filepath, patch hash, url, etc.

As an aside, with this UI it could be rather straightforward to do a pijul-backed FUSE or 9P filesystem, but I haven’t thought much about that yet.

EDIT: tldr from irc:

3:55:47 PM <pointfree> The idea is to use pijul like the unix cp command but with awareness of whether the source and destination are hunks, filepaths, patches, or branches or some combination of those.
3:58:09 PM <pointfree> The arguments by default work like a dry run (they are queries). Prefixing an argument with -w will make it writeback.
4:00:53 PM <pointfree> So pijul branch1 branch2 shows a diff between branch 1 and 2. pijul -w branch1 -w branch2 will synchronize the two branches (apply the diff to branch 1 and 2).
4:02:42 PM <pointfree> I mapped this all to existing pijul commands in tables so it shouldn’t require any backend rework to implement.

EDIT2: I noticed all of these commands are effectively symmetrical. Maybe we could get by with just a single -w flag?