Selectively updating working directory - mercurial

I'm working on some code with a partner. Our make files differ slightly courtesy of different build setups. Because of this, so far we have not been tracking this file. However it would be nice to have at least one of ours tracked. The problem is, when that is done and the other person runs hg update, their copy gets update and the code won't compile.
Is there a way to track the file, but have it such that you can update the working directory selectively? Or is there some other way I should deal with this problem?

This is a slight variant of the standard "how do I deal with a config file" question. The standard answer in SVN, Mercurial, and Git is: don't track the file, instead track <file>.example. Then each user copies that over to <file> and tweaks it as needed.
But Makefiles are a bit smarter than config files: they execute code and can include other files. In which case, it starts making sense to track the Makefile normally and have it include another local file if it's present that overrides the default rules. For instance, the following will work with GNU Make:
# pull in any local user tweaks
-include Makefile.local

MQ extension is the best and The Right Way (tm) to do it (not easiest, but...)
Store common part of file in repo, individual personalisation - in own MQ-patches

Is it possible to combine your Makefiles? Then there is not chance of losing your different configurations by not storing them in version control.
For example, you could add a conditional statement based on the username. My username is ryan and this code echos my name, but if it is run on your computer, it probably will echo "not ryan."
all:
if [ `whoami` = "ryan" ]; then echo "ryan"; else echo "not ryan"; fi

Related

Mercurial - Add tag to committed files on commit

We are looking for a way to add / update a custom tag at the beginning of each file being committed during a commit. Its some kind of local timestamp we need.
I was thinking of hooks.
Unfortunately I cannot find a useful hook for that:
precommit: unsuitable as it fires before hg knows any metadata of the commit
pretxncommit: unsuitable, as the documentation clearly states that we should not change the working dir at this point
commit: unsuitable, as it fires when the commit has already happened.
EDIT:
I can not use hg's inline changeset-hash and / or datetime. For the following reason:
Our files get later imported into an external system (we do not have control over) which does not support any kind of versioning.
To simplify stuff: let's say tag is an ever-incrementing no. (everytime we commit). This tag is then used to help getting an idea of the version / status of the file on the system in respect to the file in the repo - like "no. of changes we're missing" and such.
Any ideas?
I would suggest a two-stage solution. First, create an alias along the following lines:
[alias]
tcommit = !tag-changed-files && $HG commit "$#"
Here, tag-changed-files would retrieve a list of modified and added/moved files via $HG status -ma -n or $HG status -ma -n -0 and tag them. I am assuming that re-tagging files that have been modified but aren't being committed yet is a harmless operation; more on that below. Note that you can even redefine commit if you absolutely want to via:
[alias]
commit = !tag-changed-files && $HG --config alias.commit=commit commit "$#"
However, this is potentially problematic, because it may confuse scripts.
You could also integrate the commit step in the program if you wanted to, and even try and parse the command line arguments to only tag those files that you are committing. For this approach, using hglib might be appropriate to avoid the overhead of invoking Mercurial multiple times. (Note that hglib and other tools that use the command server ignore aliases and command defaults, so this works even if you alias commit).
Second, you'd install a pretxncommit hook that verifies that files that are being committed have indeed been tagged appropriately (to ensure that the tag-changed-files program hasn't been bypassed by accident).
This should work without a problem on full commits; for partial commits, any files that were changed but have not been committed would also have been retagged, but since they will be either committed later (and get tagged properly at that point) or reverted, that should be harmless.
an idea of the version / status of the file on the system in respect to the file in the repo
Just one idea
Stop reinvent the wheel
Incremental counter is just shit, if you task is "to know, which version is on LIVE and which - in Mercurial's tip" (and this is your real business-task, yes?!)
Keyword Extension give you last changes per file.
If you want to inject changeset of repository into files (it's reasonable good way), re-read this part of wiki-page
If you just want to version your entire repo, do not use this
extension but let your build system take care of it. Something along
the lines of
hg -q id > version
before distribution might be well enough if file-wise keyword
expansion in the source is not absolutely required
You can insert hg id output into files at export stage (in planetmaker's sed-style), bu you can also have this additional metadata in files permanently in VCS with special encode|decode filters
There is - to my knowledge - no intrinsic system in mercurial which supports what you describe. However I can recommend an approach which somewhat is adopted from building a software release package from the repository: Make a small export script which replaces a certain KEYWORD in your files with the version information you need. A Makefile target could look like which creates a zip export for revision XXX with version information in all files which support it (thus contain the verbatim KEYWORD - use something truely unique here):
VERSION=$(hg log -rXXX --template="Version: {node|short} from {date|isodate}")
export:
hg archive -rXXX -t files export
for i in $(hg ma -rXXX); do sed -i "s/KEYWORD/$VERSION/g" $i; done
zip -9rq export.zip export
I use a similar approach in my Makefiles where I create versioned export for the source of a particular revision of my software.
EDIT: if your purpose (as stated by the comment) is only to implant the number of commits made to that file: then you can use indeed a pre-commit hook and modify the file. You can count the number of modifications made to a file with hg log FILENAME --template="{node}\n" | wc -l. Do that for every file and do the sed replacement in the header of each file in the pre-commit hook.

How to get the working directory of the command from an hg hook?

I'm working on a commit hook for Mercurial and running into problems with relative paths.
Say my hook wants to look at the contents of the files being committed and warn if any contain the phrase "xyzzy". However, the user has decided to call commit from a subfolder and pass in the name of the file as a pattern...
C:\clone\subdir> hg commit file.txt -m 'test'
My hook is called with C:\clone as the working directory, but HG_PATS contains simply file.txt with no subdir\ prefix. How can I get the working directory of the hg command itself? I can't find a way to do this in docs.
The only way I can figure out how to get it is look up the process tree to find the first hg.exe and get its working directory. But that's not exactly portable to other OS's. (And I know I could write an extension, but would really like to avoid that.)
If you use the pretxncommit hook then you are given $HG_NODE which is the commit id, but the commit hasn't been finalized at that point so you can still return 1 to cancel it.
Then you could use
hg log -r $HG_NODE --template '{files}'
to get the list of files in the commit, and it gives you the full path relative to the repo root.
It's not exactly what you were after but it might get you close enough to let you do the content examination you want.
Thanks for the answers and comments, but after some more research I determined there's no clean way to do what I want from an external hook. I did implement the CWD hack I mentioned in my question. Not a ton of code, but quite nasty, and on Windows it requires undocumented access to external process CWD via tlist.exe. It works, but..yuck.
The right way to do this appears to be to write an in-process hook (example library at hghooklib). Usual versioning caveats apply as with writing any extension, though I think for our hooks the interface to hg is simple enough that we'll be ok.
(In my question I mentioned I didn't want to write an extension, but I was thinking of a full extension like hgeol. A hook-only extension with a single function entry point feels more constrained and simple, which is what I want at this point.)

Make: Redo some targets if configuration changes

I want to reexecute some targets when the configuration changes.
Consider this example:
I have a configuration variable (that is either read from environment variables or a config.local file):
CONF:=...
Based on this variable CONF, I assemble a header file conf.hpp like this:
conf.hpp:
buildConfHeader $(CONF)
Now, of course, I want to rebuild this header if the configuration variable changes, because otherwise the header would not reflect the new configuration. But how can I track this with make? The configuration variable is not tied to a file, as it may be read from environment variables.
Is there any way to achieve this?
I have figured it out. Hopefully this will help anyone having the same problem:
I build a file name from the configuration itself, so if we have
CONF:=a b c d e
then I create a configuration identifier by replacing the spaces with underscores, i.e.,
null:=
space:= $(null) #
CONFID:= $(subst $(space),_,$(strip $(CONF))).conf
which will result in CONFID=a_b_c_d_e.conf
Now, I use this $(CONFID) as dependency for the conf.hpp target. In addition, I add a rule for $(CONFID) to delete old .conf files and create a new one:
$(CONFID):
rm -f *.conf #remove old .conf files, -f so no error when no .conf files are found
touch $(CONFID) #create a new file with the right name
conf.hpp: $(CONFID)
buildConfHeader $(CONF)
Now everything works fine. The file with name $(CONFID) tracks the configuration used to build the current conf.hpp. If the configuration changes, then $(CONFID) will point to a non-existant .conf file. Thus, the first rule will be executed, the old conf will be deleted and a new one will be created. The header will be updated. Exactly what I want :)
There is no way for make to know what to rebuild if the configuration changed via a macro or environment variable.
You can, however, use a target that simply updates the timestamp of conf.hpp, which will force it to always be rebuilt:
conf.hpp: confupdate
buildConfHeader $(CONF)
confupdate:
#touch conf.hpp
However, as I said, conf.hpp will always be built, meaning any targets that depend upon it will need rebuilt as well. A much more friendly solution is to generate the makefile itself. CMake or the GNU Autotools are good for this, except you sacrifice a lot of control over the makefile. You could also use a build script that creates the makefile, but I'd advise against this since there exist tools that will allow you to build one much more easily.

git and html files

I would like to keep two versions of a static html file in my git repository. Both are basically identical, except for links for scripts, media etc (dev version vs. live version).
Right now I keep the dev version in repo, and overwrite the live version values manually on the live machine (=I have local git changes there). I am not happy with this setup, because there's manual labour for each push/pull.
What is the best flow for managing files that cannot be split into config/rest sections (like HTML)?
You could...
Remove the file from your repository and just manually populate it. If it doesn't change very often, this works just fine.
Remove the file from your repository, and generate it from a template via a post-merge script in .git/hooks/post-merge (this hook is run, for example, after git pull).
Name the file after the branch or hostname or some other variable (e.g., static.master.html vs. static.develop.html, etc) and dynamically determine which one to use at runtime.
Those are some ideas. I imagine other folks will contribute additional suggestions.
Expanding on the 2nd bullet point by larsks:
You could keep two copies in the repo (say it were your homepage) index.dev.html and index.prod.html. On the remote, your post-merge script could do something like:
cp -a index.prod.html index.html
or
truncate -s 0 index.html
cat index.prod.html >> index.html
Another problem beside renaming is to keep the content of the both files in sync. So having dedicated files for the same reason only differing in one minor path is a lot of redundncy, if you change one, you have to think on updating the other as well.
OK, you stated that the HTML file is static, but here a line of PHP to generate the difference would solve our problem
Achim

How do I change the template .hgignore used for new repositories?

When I create a new repository, I can ask TortoiseHG to give me a .hgignore file. Is there a way that I can customise what that file will look like, rather than having to go and get one manually from somewhere every time?
It's an old question, put still popped up as the first result on google, so here is an update:
In the TortoiseHg settings under the tab TortoiseHg users can specify the path of a Repo Skeleton. You can put your predefined .hgignore there, and it will be automatically copied during hg init.
See also:
#3569 Allow user-defined default .hgignore file when creating a new repository
TortoiseHG Docs
Like Tim already said in his comment, apparently it's not possible to do this.
Take a look at the following issue from TortoiseHG's bug tracker:
#966 Include some reasonable defaults in .hgignore on repo creation
Quotes from this link, both by Steve Borho (THG project lead):
This topic comes up on the Mercurial mailing list once a year or so and Matt always shoots it down. There is already support for user level ignore files; one could add these globs to a global file and be done with it.
and:
If a user has files or directories that they always want to ignore, they can add those to a global ignore file without having to introduce any new behaviors in THG.
So putting the things you always want ignored in a user-global ignore file seems to be the only option (even though it's not exactly what you're asking for):
Would like to create some defaults for my .hgignore files in TortoiseHG/Mercurial
(the question that I posted in my comment above)
Global hgignore usage