monky icon indicating copy to clipboard operation
monky copied to clipboard

Add some support for staging/unstaging individual hunks

Open ncalexan opened this issue 5 years ago • 9 comments

Right now, Monky is file-centric: staging and unstaging works at the level of files. Historically, this is appropriate: most Mercurial commands filter by files. But newer Mercurial commands support "interactive" modes which operate at finer grains: hunk by hunk and line by line. What can we do to support this in Monky? I expect this to be very technically intricate, but worth discussing.

Under the hood, Mercurial's interactive operations are managing patch files. There's no magic here, other than that they apply the patches slightly different than hg patch does. Monky could, with effort, manage staged and unstaged hunks. It would be challenging to accommodate true git-style staging, but even that might be possible with a little Mercurial extension magic and in-memory diffing.

So suppose we aimed lower: could we teach Monky to handle staged and unstaged hunks and drop everything on the floor in the case that the status buffer is refreshed? (And ignore changes to the working directory behind Monky's back.) Right now staging a file refreshes the status buffer, but that's for convenience rather than a real requirement (and is bad for performance, especially in large repositories).

I'm also experimenting with work-flows that use, say, ediff to apply hunks in sequence before running hg patch, etc.

ncalexan avatar Jul 29 '19 21:07 ncalexan

#85 is related. #91 might be related, although that might look like applying a patch to the working directory rather than to the repository.

ncalexan avatar Jul 29 '19 21:07 ncalexan

I'm massively in favour of this :)

I don't have the time to build this myself, but if you fancy putting up a PR, I will support you as best I can.

Wilfred avatar Aug 08 '19 22:08 Wilfred

I'm massively in favour of this :)

Great! At least you're in favour.

I don't have the time to build this myself, but if you fancy putting up a PR, I will support you as best I can.

It's very difficult: for small repositories, a viable approach might be to create a transient git repository and use the index there!

I have been vaguely thinking about a Mercurial plugin that:

  • takes the index as a patch (from input)
  • overlays the patch as an in-memory commit
  • computes status, etc from the working directory to the in-memory commit

That's basically what the git index does (except that git accounts for the index in all of its commands). That would allow monky to "manage the index patch hunk-by-hunk", which feels possible, but still leverage Mercurial for hg status, etc. Committing the index patch is then equivalent to hg apply.

This is not something I can seriously pursue at this time, but I'll circle back to it occasionally as I can. Perhaps something will be possible.

ncalexan avatar Aug 12 '19 16:08 ncalexan

I'm using 'hg commit --interactive' for now. Hunk commits would be very useful, even on a single file level.

Demosthenexx avatar Nov 19 '19 17:11 Demosthenexx

This probably isn't interesting to many people, but: I just shelved a commit that started experimenting with this with the commit message:

It's pretty clear that this can be made to work on the `monky` side.
On the Mercurial side, I'm fairly convinced that it's not viable.
Mercurial assumes that changes are coming from the working directory
and various efforts to bring changes in "from the side", i.e., from
patches with `files` not a subset of `status.modified` in the working
directory ran into problems.

I conclude that it's likely to be more fruitful to support
`--interactive` selection out of the box.  I'm thinking that we can
pop to an Emacs mode that is `crecord`-like for `hg commit -i`, and
perhaps even have a `crecord`-like interface within `monky` that is
used at commit time.  There are hard questions about what to do when
the working directory and `monky` diverge (is it possible that `hg
commit -i` handles a hand-edited patch creating an entirely new file?
I don't know and it seems unlikely) but for normal use this might Just
Work.

I'll keep poking at my index hg extension -- I'm by no means a Mercurial expert -- but I really feel like this approach (having Mercurial manage the index as a patch) is swimming against the current.

ncalexan avatar Feb 28 '22 17:02 ncalexan

@ncalexan Did you ever discuss this with the mercurial developers/existing extension writers?

melutovich avatar Aug 31 '23 15:08 melutovich

It seems much more mercurial-ish to me to make commit and amend it (possibly many times) before pushing, not to work on defining what is staged before committing. Especially with evolve extension (which improves hg amend and hg commit --amend and makes those commands much safer as successive versions are kept as hidden changesets).

So instead of working on patch, I would simply commit straight away whatever user selected, then apply further actions by amending this commit.

Mekk avatar Sep 27 '23 17:09 Mekk

Regarding „selected changes commit”, it probably makes sense to look at how TortoiseHG does that. See here, especially fragments with partials: https://foss.heptapod.net/mercurial/tortoisehg/thg/-/blob/branch/stable/tortoisehg/hgqt/commit.py (the --partials option is some thg extension, also implemented there https://foss.heptapod.net/mercurial/tortoisehg/thg/-/blob/branch/stable/tortoisehg/util/partialcommit.py )

(mayhaps devs could be persuaded to move this or similar feature to core mercurial or to publish this extension as independent tool, looks like thing which various GUIs would use)

Mekk avatar Sep 27 '23 17:09 Mekk

@ncalexan @Wilfred

Besides the above comments by Mekk there is a related mercurial list thread https://lists.mercurial-scm.org/pipermail/mercurial/2023-September/106330.html

melutovich avatar Sep 27 '23 17:09 melutovich