Hg pull / clone [duplicate] - mercurial

This question already has answers here:
How to do a hg update or clone in one line of bash?
(2 answers)
Closed 8 years ago.
I have a situation where I'm writing for a system that handles lots of repository, configuration, build and running stuff. There's a task which might as well be called sync-repository which the user should be able to call to ensure that the latest version of the repository gets to the client.
It's possible that the repo is already present, in which case I'd like to do a hg update. It's also possible that the repo isn't present, in which case I'd like to do a hg clone. The user shouldn't have to care which is the case. Oh, and the repository is big, so just wiping the directory and cloneing every time isn't an option.
Does hg provide a single command that clones or updates under the hood, depending on which is appropriate? Or am I going to have to do it with bash?

The user shouldn't have to care which is the case.
Yes, but YOU must care and know, does you have clone or no. How you want to manage it?
If you have someconfig-file in form, f.e
Reponame = /full/path/to/clone
you can detect, if clone exist or not and use if-then-else logic. If you haven't information, you can't make decision
Add-on
No, the are not such "combined" command in Mercurial core (I hope, they never appear in it), because Mercurial doesn't go git-way "one command for different unrelated tasks" and follow Unix-way ("Mind your own business!") more strictly
But, from other side, it give you freedom do what you want - you can define own Mercurial commands (if you asked this), which may be a hodgepodge of unrelated original commands (see Aliases extension (wiki page is slightly outdated) and [alias] section in .hgrc - up to date) and even use shell commands in Mercurial aliases

Related

Is it possible to change the username on a mercurial changeset based on the commit message?

I am converting a CVS repository (actually a number of them) into a Mercurial setup, and was wondering if any one had experience with updating and correcting usernames in the changesets.
The issue is that over quite a long period of time a default user has been used fairly often to commit to the CVS repository, and the commit message has then been supplied with '(initials)' at the end to identify the actual person committing. And now that I am converting to Mercurial I would like to clean this up, by setting the correct username.
Having done some research this seems non-trivial and I was thinking that something along the lines of this:
convert to hg and tag/branch commits with a specific initial in the commit message, using --config convert.cvsps.mergeto='{{mergetobranch ([-\w]+)}}'
converting this new repository and then use the --authormap to edit the default user to the persons initials.
But I am unsure if it is possible to selectively convert out branches and then get it back into its original place in the history.
Any help or ideas would be greatly appreciated. I have of course fully control of all the repository clones since it is not published in any way.
You need to use the Convert extension. You can follow the answer from this post.
The Convert extension sadly doesn't provide a convenient way to have conditional author mappings, but it does permit performing the conversion incrementally. You can then perform your conversion in small steps, inside of which a single author map is valid. You can use also script the generation of these "fence post" commits.
I had a similar problem today, where I wanted to conditionally change the username in some old commits in a Mercurial repository. I've bundled up all of my steps into a convenient script, which you can find here. The downside is that it depends on some Mercurial specific behavior, but you can work around this by first converting with a basic, non conditional author map, and then running the conditional conversion on the that repository.
This question is rather old, but if you don't have too many clones out in the wild, it may still be worth your while to run the author-name correcting conversion. Remember: hg convert necessarily changes the hash for every changeset, so you have to deal with all the usual issues of EditingHistory. I suspect this is part of the reason why both of the usual ways of dealing with this, Mercurial Queues and the newer HistEdit Extension, don't play nice with merge changesets -- it's difficult and messy to redo a non-leaf merge, and the presence of merges often indicates that you've shared the repository, which means you should reconsider editing history.

How good is my method of embedding version numbers into my application using Mercurial hooks?

This is not quite a specifc question, and more me like for a criticism of my current approach.
I would like to include the program version number in the program I am developing. This is not a commercial product, but a research application so it is important to know which version generated the results.
My method works as follows:
There is a "pre-commit" hook in my .hg/hgrc file link to version_gen.sh
version_gen.sh consists solely of:
hg parent --template "r{rev}_{date|shortdate}" > version.num
In the makefile, the line version="%__VERSION__% in the main script is replaced with the content of the version.num file.
Are there better ways of doing this? The only real short coming I can see is that if you only commit a specfic file, version.num will be updated, but it won't be commited, and if I tried to add always committing that file, that would result in an infite loop (unless I created some temp file to indicate I was already in a commit, but that seems ugly...).
The problem
As you've identified, you've really created a Catch-22 situation here.
You can't really put meaningful information in the version.num file until the changes are committed and because you are storing version.num in the repository, you can't commit changes to the repository until you have populated the version.num file.
My solution
What I would suggest is:
Get rid of the "pre-commit" hook and hg forget the version.num file.
Add version.num to your .hgignore file.
Adjust version_gen.sh to consist of:
hg parent --template "r{node|short}_{date|shortdate}" > version.num
In the makefile, make sure version_gen.sh is run before version.num is used to set the version parameter.
My reasons
As #Ry4an suggests, getting the build system to insert revision information into the software at build time, using information from the Version Control System is a much better option. The only problem with this is if you try to compile the code from an hg archive of the repository, where the build system cannot extract the relevant information.
I would be inclined to discourage this however - in my own build system, the build failed if revision information couldn't be extracted.
Also, as #Kai Inkinen suggests, using the revision number is not portable. Rev 21 on one machine might be rev 22 on another. While this may not be a problem right now, it could be in the future, if you start colaborating with other people.
Finally, I explain my reasons for not liking the Keyword extension in a question of mine, which touches on similar issues to your own question:
I looked at Mercurials Keyword extension, since it seemed like the obvious solution. However the more I looked at it and read peoples opinions, the more that I came to the conclusion that it wasn't the right thing to do.
I also remember the problems that keyword substitution has caused me in projects at previous companies. ...
Also, I don't particularly want to have to enable Mercurial extensions to get the build to complete. I want the solution to be self contained, so that it isn't easy for the application to be accidentally compiled without the embedded version information just because an extension isn't enabled or the right helper software hasn't been installed.
Then in comments to an answer which suggested using the keyword extension anyway:
... I rejected using the keyword extension as it would be too easy to end up with the string "$Id$" being compiled into the executable. If keyword expansion was built into mercurial rather than an extension, and on by default, I might consider it, but as it stands it just wouldn't be reliable. – Mark Booth
A don't think that there can be a more reliable solution. What if someone accidentally damages .hg or builds not from a clone but from an archive? – Mr.Cat
#Mr.Cat - I don't think there can be a less reliable solution than the keywords extension. Anywhere you haven't explicitly enabled the extension (or someone has disabled it) then you get the literal string "$ID$" compiled into the object file without complaint. If mercurial or the repo is damaged (not sure which you meant) you need to fix that first anyway. As for hg archive, my original solution fails to compile if you try to build it from an archive! That is precisely what I want. I don't want any source to be compiled into our apps without it source being under revision control! – Mark Booth
What you are trying to do is called Keyword Expansion, which is not supported in Mercurial core.
You can integrate that expansion in make file, or (simpler) with the Keyword extension.
This extension allows the expansion of RCS/CVS-like and user defined keys in text files tracked by Mercurial.
Expansion takes place in the working directory or/and when creating a distribution using "hg archive"
That you use a pre-commit hook is what's concerning. You shouldn't be putting the rest of version_gen.sh into the source files thesemves, just into the build/release artifacts which you can do more accurately with an 'update' hook.
You don't want the Makefile to actually change in the repo with each commit, that just makes merges hell. You want to insert the version after checking out the files in advance of a build, which is is what an update hook does.
In distributed systems like Mercurial, the actual "version number" does not necessarily mean the same thing in every environment. Even if this is a single person project, and you are really careful with having only your central repo, you would still probably want to use the sha1-sum instead, since that is truly unique for the given repository state. The sha1 can be fetched through the template {node}
As a suggestion, I think that a better workflow would be to use tags instead, which btw are also local to your repository until you push them upstream. Don't write your number into a file, but instead tag your release code with a meaningful tag like
RELEASE_2
or
RELEASE_2010-04-01
or maybe script this and use the template to create the tag?
You can then add the tag to your non-versioned (in .hgignore) version.num file to be added into the build. This way you can give meaningful names to the releases and you tie the release to the unique identifier.

Branching with Mercurial SCM

So right now I'm learning Ruby on Rails, and I'm working through the book "Agile Web Development with Rails". I've also decided that I want to give Mercurial a go, because I've read up on distributed SCM's, and it seems like an ideal situation. I still, however, prefer to push my code remotely to my Linux VPS just incase my hard drive decides to take a dive.
So, my question is specific to branching in Mercurial. Right now I've got a remote repository set up and I can push changes over SSH easily (hell I even set up an Nginx FastCGI site that lets me push, too). What I'd like to do, however, is create branches for each chapter as I work on them, so I can keep a nice organized history of my progress through the book. So this is what I'm doing:
$ hg branch chapter-10
(do chapter 10 stuff)
$ hg commit -m "Chapter 10 complete"
$ hg update default
$ hg merge chapter-10
$ hg commit -m "Merging chapter 10 into default"
$ hg push
Once I execute the push statement, I get this message from Mercurial:
pushing to ssh://myserver/hg/depot
searching for changes
abort: push creates new remote branch 'chapter-10'!
(did you forget to merge? use push -f to force)
So at this point I try to do an hg merge again, and it tells me there's nothing to merge, which is obviously true because I just merged it. When I force the push with -f, everything seems fine, and even the web interface shows the appropriate branches.
To sum up, my question is simple: Am I doing this the right way? Is there a more appropriate way to do this with Mercurial (i.e. the "Mercurial way")? Honestly I just want the repository to serve as a backup. I'm a fan of the distributed SCM model, but to me it feels sorta "dirty" to force pushes. Any insight is greatly appreciated! Thanks in advance.
The push -f is the right option for your case, and there was a discussion last month to add that command when this "push creates new remote branch" warning pops up: see issue 1513.
However, issue 1974 (this month) mentions some undesirable effects (not in your case though).
See this translated article to know more about creating a second head on a remote repo.
On the more general point, you can use branch if you are writing your chapter in parallel, and you want to merge them only at certain (stable) point in time
But if your writing process is more linear, you could use only one branch, and put some tags along the way.
However, should you go back to chapter 10 and add some lines, even though you already put tags 11 and 12, that would make the history harder to read. So branches are still a good idea in this case.
I don't know about your specific problem, but from your comments it seems that you use branches where you probably wanted to use tags.
Branches are generally used when multiple people cooperate on the same project and you want to create a work separation so one person can work on a stable piece of code, while the other does something experimental that temporarily breaks functionality. Alternatively branches are used to stabilize for release, while development is going on in trunk.
Tags (or labels) are used to primarily create a marker signifying some importance to the version of code. Like for example if you want to mark a completion of chapter 10, you just tag all current versions with a 'chapter-10' tag. There is no need to branch. You can branch from a tagged version at any point in future if it would be necessary for some reason.
In this case I feel that it's totally ok to use -f for the push. It just creates new branches, not heads. Creating remote heads is another matter entirely.

Does anyone have a script to handle multiple hg repositories at once?

I have a project that is combining multiple hg repositories (different components) to build a single application. I'm looking for a cross-platform tool to support performing an operation on multiple repos at the same time (e.g. tag, pull, push, commit etc...) Essentially, I'm looking for the 'repo' script that Google wrote for Android, but for hg instead of git:
http://source.android.com/download/using-repo
I searched on stack overflow and found this:
mercurial windows batch file for pulling changes to multiple repositories
But it's still a bit manual and windows only. I know it's not that hard to write the script to either pass a command to the repos or try to encapsulate everything, but thought that it might be a common thing so maybe others already have a solution. I suppose one approach would be to port the repo script to hg (find and replace git with hg would probably get pretty far for simple operations).
What do other people do in this situation?
Definitely look at the new (in version 1.3) subrepositories feature in Mercurial. It lets you have an overarching repository that contains other repositories. The state of the top level includes a file that specifies the hash of the tip of the sub-repos, so you can effectively specify a single hash node id that encompasses the state of all the subordinate repos.
https://www.mercurial-scm.org/wiki/subrepos
I have been in a similar scenario for the past year, working daily with a project spread over 6 repositories, and being the one responsible for most branching/merging stuff etc.
At some point I found a simple bash-script for checking multiple SVN repo's. I adoptet it to Mercurial and have extended it over time. Right now I can't recall or google the original source of the script, so I unfortunately can't credit the original author (will credit in my script if I find the info later).
My "hgall" script is published on GitHub at https://github.com/JKrag/hgall
It is made for my own use, and thus directly references a few extensions that I have been using, but this can been easily edited out. (or just don't use the commands that call extensions you haven't installed).
The script is documented in the README, including my personal "tweak" of having it (by default) ignore repo's that start with underscore, as I use these as temporary clones to test messy operations (e.g. large merges).
I hope this script is useful to some of you - it has been of great help to me over the last year. Our company has just moved to Git, so I will probably not be making many updates in the near future, but might possibly be porting it to Git some day....
Additionally, Iain Lowe has an extension https://bitbucket.org/ilowe/multirepo/src which can manage multiple repositories.

Fetching a single file from another mercurial repository [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Mercurial: copying ONE file and its history to another repository
I have several repositories in my local machine.
One is my main code, another is an assortment of useful code/tools.
These are two fundamentally different repos. It might make sense to setup a new repo and pull these two in as sub-repos, but I want to wait until Mercurial devs mark sub-repos as non-experimental before I do that.
One of the useful code files has become so useful, I want to put it into my main code area...but I want to maintain its history. This will, of course, result in some variant of a fork, but that's acceptable. (best case would be being able to push-pull it back and forth and keep updating its history).
I'd just use the subrepo feature that came online in 1.3. It might change slightly, but you won't be left high and dry backwards compatibility wise.
If you can't bring yourself to so, then what you need to do is:
use hg convert with a filemap that deletes all files except the one you want and convert from the repo with the single useful file to a new repo containing only that file and all its history
then hg pull from the new single-file-full-history repo into the target repo
hg merge in the target repo and you'll have that file with all it's history
The other option would be to hg export the entire tools repo, use grepdiff (part of difftools) to limit to only one file, and then import into the target repo, but that's crazy.
The short answer is you can't copy a file and its history simply, as stated in this thread:
https://www.mercurial-scm.org/pipermail/mercurial/2009-April/025105.html
I'm relatively new to DVCS and you really have to think of each repo as a self contained package. Not like svn or p4, where you can hang different projects off the root and configure it how you like and do partial repo checkouts. (That said, I really like the flexibility of being able to clone repos quickly to try things out. And being able to commit on a local machine.)
I'm just looking at a similar problem. I've branched a repo to make changes and I only want one file out of one changeset. And it is nice to have the history.
You could look at:
hg cat
This would probably involve writing a script to transfer history, i.e. commit N changesets in the target repo with the hg cat results from the source. Wonder if there is an extension to do this?
You could get the log of the file you want to copy and paste that into a commit comment. It's not in the metadata, but you do have a record and all the hashes etc.
may be
hg export
also can help you.