pure
pure copied to clipboard
Mercurial support?
General information
- Pure version: Not sure how to get this. I just installed it today with zplug
- ZSH version: zsh 5.1.1 (x86_64-ubuntu-linux-gnu)
- Terminal program & version: GNOME Terminal 3.18.3
- Operating system: Ubuntu 16.04
- ZSH framework: zplug
I have:
- [x] Tested with another terminal program and can reproduce the issue: Hyperterm
- [x] Followed the Integration instructions for my framework
Problem description
Any chance of adding Mercurial support? I would like the same indicators that you have for Git. i.e., I want to know what branch I'm currently on, when the repo is dirty, and ideally when there is incoming or outgoing changesets.
Reproduction steps
-
cd
into a Mercurial repo (with.hg
directory in it)
My .zshrc
:
zplug mafredri/zsh-async, from:github
zplug sindresorhus/pure, use:pure.zsh, from:github, as:theme
Unfortunately Pure does not support mercurial. I personally don't use mercurial at all, nor do I have enough knowledge about it to implement it in Pure.
One thing you could try is:
autoload -Uz promptinit; promptinit
prompt pure
zstyle ':vcs_info:*' enable git hg
zstyle ':vcs_info:hg*' check-for-changes true
zstyle ':vcs_info:hg*' stagedstr '*'
zstyle ':vcs_info:hg*' unstagedstr '*'
zstyle ':vcs_info:hg*' formats '%b%c%u' '%R'
zstyle ':vcs_info:hg*' actionformats '%b|%a%c%u' '%R'
I'm uncertain if this will work, but it should show you branch name and dirty status. Here %c
is for staged changes, %u
is for unstanged changes, both would show **
in this configuration. I also can't give any guarantees that this will work in the future.
Generally Pure doesn't rely on vcs_info much and for dirty, fetch, and arrows Pure calls git
directly, so unfortunately I'm unsure how those features could be enabled without modifications to Pure.
All this being said, I would not be opposed to supporting mercurial in Pure, given a well thought-out PR that takes performance into consideration.
PS. For more information about vcs_info
(I'm no expert) please consult the man pages ( man zshcontrib
, search for vcs_info
).
Your solution shows the branch name (without space, directly next to directory name) but no dirty status. Oh well, thanks anyway.
Too bad =/, I hadn't actually tested this, just wrote it down based on documentation. I believe if you play around with the vcs_info
configuration a bit, you should be able to get the dirty status to work as well. Sorry that's all I can provide at this moment.
I'll keep your request for mercurial support in mind for the future.
OK, I've got basic Mercurial support over on my fork with async dirty checking. Will try figuring out the incoming/outgoing stuff later. I know next to nothing about shell scripting so it's tough-going.
Awesome!
One tip, you can use %s
, e.g.:
zstyle ':vcs_info:*' max-exports 3
zstyle ':vcs_info:*' formats ' %b' 'x%R' '%s'
This will insert either git
or hg
into $vcs_info_msg_2_
, should make the code clearer and not require the separate formats just to parse the working tree =).
Let me know if you need any help and feel free to open up a PR when you feel it's a good time to discuss it further!
Thanks @mafredri. I have some question about this prompt_pure_async_git_fetch|prompt_pure_async_git_arrows
if you don't mind answering them.
- I don't really use git, so I'm not quite sure how this "fetch" works. Is Pure actually downloading the remote changes, or is it just checking if there are any?
- The "git arrows" -- does the down arrow mean there are changes waiting to be downloaded, or changes that have been downloaded but not yet merged? And 'up' means you've committed but not yet pushed, right?
- Why isn't git fetch throttled like you did with the dirty check? Are dirty checks just really slow in git, whereas fetches are quick? What is considered a "large" repo? The main project I work on has 17354 files and over a million lines, and a dirty check in Mercurial takes ~110 ms. However, an "incoming" check takes ~1.9 seconds.
In Mercurial, you can use hg incoming
to check if there are any new remote changesets, but it doesn't download them. hg pull
downloads the changesets locally, but doesn't apply them to your working directory. If one of these changesets is on the same branch you're working on, then it will create a new head, and you can hg merge
to merge it in, otherwise you can use hg update
to simply 'go' to to that changeset (update working directory).
I'm trying to decide if I should throttle the "hg incoming" check or not, and whether or not I should automatically pull changes. I feel like I shouldn't pull the changes, just check if they exist. Pulling won't mess with your working directory, but it does modify your local copy repo.
The other thing I'm trying to figure out is what a down arrow should mean:
- There are incoming changesets on the current branch
- There are incoming changesets on any branch
- There are multiple heads (i.e. you need to merge before you can push)
Thoughts?
Yay, this is the kind of Mercurial know-how that's needed to implement this in Pure, glad you're putting in the effort @mnpenner!
-
git fetch
actually downloads objects and refs from a remote repository (e.g. GitHub). Only the objects though, no changes are done to any of your branches, etc. It just means the data is now available locally. - The down arrow means that your current branch has new commits on the remote that are not yet applied to your local branch. Now, due to
git fetch
these changes (objects) are already present in your local repository, just not applied to the branch. Up is as you suspected. - The TL;DR is that we would not throttle git status if it was avoidable. Whenever a git repo is large enough that the files do not fit in the filesystem cache, things quickly become slow. When this happens, git status would consume a bunch of CPU, so the throttling is in place to prevent git status from eating CPU on every terminal command. An example of a really large git repository is the chromium repo. And generally in problematic cases we're talking
git status
that takes 30+ seconds.
I don't see any reason to implement nr. 3 for mercurial unless it becomes a problem (and even then I'm planning on removing the feature in favor of disabling the VCS features on a per-folder basis).
I'm trying to decide if I should throttle the "hg incoming" check or not, and whether or not I should automatically pull changes. I feel like I shouldn't pull the changes, just check if they exist. Pulling won't mess with your working directory, but it does modify your local copy repo.
Mercurial seems a bit more flexible than Git in this regard. The reason Pure issues git fetch
is because git rev-list
used for arrows works on the local repo, meaning the objects must be present. Querying this information from the remote on every prompt would be too inefficient.
But personally I'm a big fan of Pure automatically fetching in the background, and that's partly because e.g. issuing git pull
to fast-forward my branches is much faster since the objects are already downloaded.
I'm trying to decide if I should throttle the "hg incoming" check or not, and whether or not I should automatically pull changes. I feel like I shouldn't pull the changes, just check if they exist. Pulling won't mess with your working directory, but it does modify your local copy repo.
I'd say no to throttling, but maybe to pulling changes (I like it for Git). I'll trust your Mercurial expertise on this though, as I don't know what the benefits / downsides are. As a general rule though, if pulling speeds up checking for remote changes, then that might be preferable.
The other thing I'm trying to figure out is what a down arrow should mean:
To match Git behaviour, it should be limited to the current branch (1). With regards to (3), I assume multiple heads in this instance means your local head and the remote head? In that case, Pure would show both (down/up) arrows simultaneously (for Git).
Did that answer all the open questions? If not, feel free to ask some more =)!
I assume multiple heads in this instance means your local head and the remote head?
No, you can have multiple local heads. These are usually caused by someone else pushing a commit to the branch you're working on, but not necessarily. If you 'update' back one revision, for example, make some changes and then commit again you will created an 'unnamed branch' which is effectively two heads on the same 'named branch'. You can create as many heads/unnamed branches as you want (where a "head" is just the latest changeset on a branch).
If you try to push, and pushing will create a new head/branch then Mercurial warns you that you should merge first so as to not create another head. However, you can --force
push if you really do want to create another head in the remote repo.
But personally I'm a big fan of Pure automatically fetching in the background, and that's partly because e.g. issuing git pull to fast-forward my branches is much faster since the objects are already downloaded.
I think I agree. I don't see any downsides of pull
ing instead of simply checking the remote for incoming changesets. They seem to take about the same amount of time anyway. Another benefit is that if you lose internet for a bit, or the remote Git/Hg server goes down, you'll still have all the changesets locally.
To match Git behaviour, it should be limited to the current branch (1)
I think Git and Hg differ a bit here. By "incoming" I mean there are changesets that were pushed to the remote repo that you have not yet pull
ed. I think this requires a bit more thought. Here's a scenario:
... --- 100 --- 101 -------- 103
\
-- 102
Let's say you're working on a named (feature) branch. You commit and push rev 100, then make some more changes and push rev 101. Then your co-worker pulls your changes, updates to the then-latest rev 101, fixes some bugs, and pushes 102. Meanwhile, you're still working away. When you're done, you commit rev 103.
Now when you try to push, hg is going to complain that this will create a new head, and you should merge first. If you do so, it will look like this:
... --- 100 --- 101 -------- 103 --- 104
\ /
-- 102 ----------
i.e., "104" will be a merge changeset. After you merge, you can commit and push without warnings.
But let's take a step back to before 104 was created. If we pull
in the changes every time Pure prompts, then 102 will be downloaded and ready to be merged, so there will be no "incoming" changes. Moreover, rev 103 is newer than 102, so its not as though "the remote repo is ahead" -- you committed last, so you get the higher revision number (N.B. in Hg revision numbers are local and might not match what everyone else sees, but the changeset hashes are unique/shared -- not sure if Git is the same).
In this scenario, I reckon a down arrow should appear because there's a changeset waiting to merged in, but a down arrow is a little misleading -- here it doesn't mean that you need to download anything, nor does it mean that you're down/behind the remote -- you've simply diverged.
Lastly, what if you created both 102 and 103 for some reason? Maybe you made a bunch of changes and committed, but then realized that code was no good, so you updated back to 101 and decided to try again from a clean slate? In Mercurial, you generally can't erase history after you've pushed, so if 102 was bad, what you would do instead and 'close' that [unnamed] branch. If a branch is closed, Mercurial won't ask you to merge it in.
So really, I don't think a down arrow makes sense to mean anything other than "there are new remote changesets that you haven't downloaded yet". This is complimentary to what the up arrow means. However, if we're always pulling, then the down arrow isn't needed at all.
Thus, I think what I should do instead is display number of [unclosed] heads on the current branch if there's more than one. This is a really useful thing to know because generally you want to merge those changes in as quickly as possible otherwise you will have lots of conflicts later.
What do you think? Should I display the number of heads, plus an up arrow if there are unpushed commits? Or I could display the number of unpushed commits too. Or we could choose a different 'icon' to mean 2+ heads and not display the number (it's more important know that there are unmerged heads than to know how many there are -- more than two has been pretty rare in my experience, but maybe not with larger teams).
Thanks for the thorough explanation, it was insightful.
After a bit of consideration, it seems to me that hg and git behavior is quite similar in many ways, for the exception that mercurial supports multiple heads for a branch.
From what I can gather, the down arrow for both git and mercurial could be nearly the same thing.
- For git, it means you must either fast-forward or merge the remote changes into your branch (git fetch has already downloaded the objects, so downloading is not involved). For reference,
git pull
is essentially (simplified) agit fetch && git merge
. - For hg, it means you can merge a changeset into your branch.
The biggest difference as I see it, is that diverging in git means you must either merge, rebase (apply your commits onto remote) or reset (delete your local commits) your branch to be able to push new changes to the remote (alternatively overwriting the remote with --force). There cannot be multiple heads as with mercurial.
With this in mind, I see the down arrow more as "there are new changes not yet in this branch". Applying this thinking to mercurial, do you think it would make sense to keep it as an indicator of unmerged changes, considering we are already downloading those changes from the remote? Of course, it would be great if what pure displays could feel intuitive to a mercurial user, at least after a short hint in the readme.
Personally I would love to simply keep the up/down arrows around and not introduce new concepts. Then again concepts between git/hg don't align 1:1. I also feel numbers are a distraction (and away from simplicity) but while they are not useful for git, maybe they give valuable information for mercurial users, idk.
I'm not really sure what other prompts are doing for Mercurial, so I can't really say what would be intuitive to Hg users. The few that I've found don't display up or down arrows.
A quick poll from my co-workers: they think the down arrow means "gotta get down on Friday" or "all below" (really helpful guys!)
Of the two serious answers I got, they thought it meant they should pull, which is what I would think too. I don't mind using a down arrow to mean "you should merge" but I think it will cause confusion. I suspect people will try pulling a few times and wonder why the arrow isn't going away. Unfortunately, I do think we need to introduce something new to represent this idea.
Historically, I usually wouldn't know there's another head until I try to push and Mercurial yells at me. Knowing beforehand would definitely be a nice perk, but it's not something I've seen before.
Suggestions for other icons: ⤩ ⛙ ↯ ⥈ ⇊☺☻
Thanks for doing a poll, it's definitely helpful to know what others think.
Ultimately I think you're right. Git get's away with the down arrow because git pull
behaves pretty much as you would expect when seeing a down arrow. Applying this thinking to mercurial seem forced.
The biggest question mark is what indication to use, in my opinion there aren't many good icons / arrows to indicate this. Here's what I came up with: ⇠ ⇤ ↯ ⇣⇡
(up/down for reference). I took a look at your suggestions as well, but maybe ↯
is the only one weird enough to work? I kind of like ⇠
for two reasons though, it matches the up arrow in design, and it points toward the branch name, maybe that is enough of a hint that it's not about downloading, about merging?
Screenshots:
PS. I merged quite a big change into Pure today, 4cdd0cf4f48d0c2064700c4fc60083bc0b3f6693. I hope this does not discourage you from working on your fork! If you wish to continue working on your current fork without rebasing / merging, I'd be happy to help port it over once it's ready.
When I finish it up I'll attempt to merge in your changes, if it doesn't work out I might ask for help 😄 Thanks.
One more consideration: if you're sitting on a branch, in a clean state (no modified files, and no unpushed changes), and someone pushes a change to your branch, then you will be behind, but there won't be an additional head.
This is different from the scenario I outlined above because it means you should hg update
to the tip of the branch, but you don't need to hg merge
. I think this is more similar to Git's workflow. Perhaps ↯
would be appropriate for this situation because it points downwards, indicating that you are behind, but it's not a straight arrow which would suggest you need to pull
.
Another possible one for merge if you want to stick with arrows: ⇆
or ⤝
or ⇐
or ↢
. It's too bad they don't have dotted versions of each of these to keep the style. Maybe for Hg we should use a solid up arrow too, so they all match? Git can keep the dotted arrows, and all of them will be override-able via config anyway.
Sorry to revive an old issue but I'm finding myself in need of Mercurial support for Pure. (I'm something of a beginner so this thread has been extraordinarily helpful - thanks!)
@mnpenner - is this something you're still interested in doing? Can I be of assistance?
I work with fairly massive git and hg repositories - Pure's async has been a lifesaver - so I'm happy to do anything I can to get clean, performant, hg support into Pure.
(Fwiw an informal poll of folks around me claim ⤩
is a winner for merge. ⨈
was also suggested but isn't arrowy enough to my eyes.)
Hey @abl, I haven't been able to work on this lately. I've been using the prompt on my fork for a few months now, but it still just has incoming and dirty flags. Even just that has been better than the other prompts out there.
If you would like to take over, that would be fantastic!
I think mafredri said he made some big changes since I started my fork. I'd start by merging that in; hopefully it's not too painful.
...still just has incoming and dirty flags. Even just that has been better than the other prompts out there.
Yep I'd agree!
I'd start by merging that in; hopefully it's not too painful.
Sounds good.
Merged in https://github.com/abl/pure - I've got some testing to do and will propose a PR when ready but feedback is always appreciated. :)
@abl Tried with
zplug abl/pure, use:pure.zsh, from:github, as:theme
Got parse error:
/home/mpenner/.zplug/repos/abl/pure/pure.zsh:405: parse error near `;;'
Let me know when it's patched up and I'll give it another whirl.
Resolved! The merge loads but doesn't work - I'll do a proper three-way reading and refactoring next week.
Ping @mnpenner @abl, are either of you still working on this, is it something you want to land in Pure 😄?
I've been tinkering with it in my spare time but mostly I've been blocked; chg
is basically required for decent performance and it's been causing issues with my work repositories. (Not sure how much of that is Mercurial and how much of that is what we're doing with it.)
Cool, happy to know this is still being worked on. Feel free to write here if you want to throw around ideas, I'd be happy to help where I can. I'm curious what performance issues there are without chg
? (I don't even know what it is.) Nothing that can be fixed by things running asynchronously?
I'm curious what performance issues there are without
chg
? (I don't even know what it is.)
hg
is Python so invocations are fairly expensive; the solution to this is the CommandServer. chg
is supposed to be a drop-in replacement that uses a persistent command server.
Nothing that can be fixed by things running asynchronously?
It's probably an artifact of the repos I'm using (and the necessary plugins including NarrowHG) but individual status commands can take 2-3 seconds to execute.
I'm trying to come up with a solution that works as well as Pure's Git support does but at the moment I've got a small cluster of plugins and Google-specific code; compounding everything is that I still don't have a great feel for how to translate Mercurial concepts to Git concepts. :)
Any updates on this? I would be willing to help if no one is working on it.
I think this would be better implemented as a plugin after https://github.com/sindresorhus/pure/issues/460 is done. Mercurial is not that common and it's not something I would want to maintain here.
Closing in favor of #460.