Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mercurial support? #313

Closed
2 tasks done
mnpenner opened this issue Apr 5, 2017 · 26 comments
Closed
2 tasks done

Mercurial support? #313

mnpenner opened this issue Apr 5, 2017 · 26 comments

Comments

@mnpenner
Copy link

mnpenner commented Apr 5, 2017

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:

  • Tested with another terminal program and can reproduce the issue: Hyperterm
  • 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

  1. 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
@mafredri
Copy link
Collaborator

mafredri commented Apr 7, 2017

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.

@mafredri
Copy link
Collaborator

mafredri commented Apr 7, 2017

PS. For more information about vcs_info (I'm no expert) please consult the man pages ( man zshcontrib, search for vcs_info).

@mnpenner
Copy link
Author

mnpenner commented Apr 7, 2017

Your solution shows the branch name (without space, directly next to directory name) but no dirty status. Oh well, thanks anyway.

@mafredri
Copy link
Collaborator

mafredri commented Apr 8, 2017

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.

@mnpenner
Copy link
Author

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.

@mafredri
Copy link
Collaborator

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!

@mnpenner
Copy link
Author

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.

  1. 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?
  2. 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?
  3. 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:

  1. There are incoming changesets on the current branch
  2. There are incoming changesets on any branch
  3. There are multiple heads (i.e. you need to merge before you can push)

Thoughts?

@mafredri
Copy link
Collaborator

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!

  1. 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.
  2. 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.
  3. 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 =)!

@mnpenner
Copy link
Author

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 pulling 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 pulled. 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).

@mafredri
Copy link
Collaborator

mafredri commented Apr 25, 2017

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) a git 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.

@mnpenner
Copy link
Author

mnpenner commented Apr 25, 2017

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: ⤩ ⛙ ↯ ⥈ ⇊☺☻

@mafredri
Copy link
Collaborator

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:
screenshot 2017-04-27 23 51 26
screenshot 2017-04-27 23 51 51
screenshot 2017-04-27 23 52 18

PS. I merged quite a big change into Pure today, 4cdd0cf. 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.

@mnpenner
Copy link
Author

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.

@mafredri mafredri reopened this Apr 28, 2017
@abl
Copy link

abl commented Jul 23, 2017

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.)

@mnpenner
Copy link
Author

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.

@abl
Copy link

abl commented Jul 23, 2017

...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.

@abl
Copy link

abl commented Jul 27, 2017

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. :)

@mnpenner
Copy link
Author

@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.

@abl
Copy link

abl commented Jul 28, 2017

Resolved! The merge loads but doesn't work - I'll do a proper three-way reading and refactoring next week.

@mafredri
Copy link
Collaborator

Ping @mnpenner @abl, are either of you still working on this, is it something you want to land in Pure 😄?

@abl
Copy link

abl commented Apr 22, 2018

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.)

@mafredri
Copy link
Collaborator

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?

@abl
Copy link

abl commented Apr 22, 2018

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. :)

@jackcogdill
Copy link

Any updates on this? I would be willing to help if no one is working on it.

@sindresorhus
Copy link
Owner

I think this would be better implemented as a plugin after #460 is done. Mercurial is not that common and it's not something I would want to maintain here.

@sindresorhus
Copy link
Owner

Closing in favor of #460.

@sindresorhus sindresorhus closed this as not planned Won't fix, can't repro, duplicate, stale Feb 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants