Create a Mercurial alias that runs two commands and takes one paramater - mercurial

I'm trying to create an alias and allows me to commit my changes and push all changesets for the current branch.
I'm running this from a Windows command prompt.
I've read this question and this question and so far have this:
ci-push = !hg ci -m $1 && hg push -b .
When I try this i get the error:
abort: Commit: The system cannot find the file specified
If I try:
ci-push = !hg ci -m %1 && hg push -b .
then it appears to work (prompts for auth and pushes the commit), but my commit message is:
%1
Is this even possible from a Windows cmd prompt?

On Windows, %USERPROFILE%\mercurial.ini:
[alias]
ll = log -l$1
Testing:
>hg ll
abort: too few arguments for command alias
> hg ll 5
changeset:...
Shell alias (%USERPROFILE%\mercurial.ini):
[alias]
ld = !hg log -r $1 && hg diff -r $1
Testing:
>hg ld 154
changeset: 154:5bb3aba44eab
....
diff -r 5bb3aba44eab ....
P.S.
When using $N with spaces you should use quotes (!hg ci -m "$1" ... in aliases).

Related

Mercurial hg(v4) get trunk commits since given revision

The screenshot shows that hg(v2) can get trunk only commits since a particular revision. In the example below, rev 1 is not a trunk commit.
How do we get trunk only commits since given rev in hg v4?
To create the hg test repository used here, run the following:
$ mkdir hg-multi-branch
$ cd hg-multi-branch
$ hg init
$ v=A && touch $v && hg add $v && hg commit -m "Added $v"
$ hg branch feature
$ v=B && touch $v && hg add $v && hg commit -m "Added $v"
$ hg co default
$ v=C && touch $v && hg add $v && hg commit -m "Added $v"
One could use the -b default opt to get commits from the default branch. However using -b is not exactly the same as --follow-parent. There are cases where the output would be different.
as #Lazy-Badger said :: range should work for you
hg log --follow-first -r 0::tip
all changesets that are descendants of x and ancestors of y, including x and y themselves.
https://www.mercurial-scm.org/repo/hg/help/revsets

How to commit many numbered old versions of a file

I'm looking for an elegant way to populate Mercurial with different versions of the same program, from 50 old versions that have numbered filenames:
prog1.py, prog2.py ... prog50.py
For each version I'd like to retain the dates and original filename, perhaps in the change comment.
I'm new to Mercurial and have searched without finding an answer.
hg commit has -d to specify a date and -m to specify a comment.
hg init
copy prog1.py prog.py /y
hg ci -A prog.py -d 1/1/2015 -m prog1.py
copy prog2.py prog.py /y
hg ci -A prog.py -d 1/2/2015 -m prog2.py
# repeat as needed
One can of course automate the whole thing in a small bash script:
You obtain the modification date of a file via stat -c %y ${FILENAME}. Thus assuming that the files are ordered:
hg init
for i in /path/to/old/versions/*.py do;
cp $i .
hg ci -d `stat -c %y $i` -m "Import $i"
done
Mind, natural filename sorting is prog1, prog11 prog12, ... prog19, prog2, prog21, .... You might want to rename prog1 to prog01 etc to ensure normal sorting or sort the filenames before processing them, e.g.:
hg init
for i in `ls -tr /path/to/old/versions/*.py` do;
cp /path/to/old/versions/$i .
hg ci -d `stat -c %y /path/to/old/versions/$i` -m "Import $i"
done

Can I disable the default behaviour `hg add` with no arguments?

When I run hg add with no arguments, it is always by mistake, and the result, adding all of the files and directories recursively, is horribly annoying and difficult to undo, especially when other files have been (correctly) added since the last commit. Is there any way to make a plain hg add just print an error message?
Try putting this in your ~/.hgrc:
[defaults]
add = -X .
That tells hg add that unless specifically named it should ignore all files (got matches all). Here's an example:
(df)Ry4ans-MacBook-Air:~ ry4an$ hg init test
(df)Ry4ans-MacBook-Air:~ ry4an$ cd test/
(df)Ry4ans-MacBook-Air:test ry4an$ vi ~/.hgrc # added the section above
(df)Ry4ans-MacBook-Air:test ry4an$ hg status
(df)Ry4ans-MacBook-Air:test ry4an$ echo this > that
(df)Ry4ans-MacBook-Air:test ry4an$ hg add # nothing added
(df)Ry4ans-MacBook-Air:test ry4an$ hg status
? that
(df)Ry4ans-MacBook-Air:test ry4an$ hg add that
(df)Ry4ans-MacBook-Air:test ry4an$ hg status
A that
In general though, you should just make your .hgignore robust enough to ignore all the files you don't want added
In your user config file (~/.hgrc), add the following to your [alias] section:
[alias]
realadd = add
add = add --dry-run
Now, just hg add will always do a dry-run. To actually add, you have to use hg realadd. Note that you could redefine the add alias to do anything, it doesn't have to be add --dry-run.
I don't know a way to do this purely with Mercurial configuration, but if you're willing to tune your bash profile, then you can redefine the hg command as a function. The function would either detect hg add and fail or otherwise do a passthrough to the real hg command.
function hg() {
if [ "$#" -eq 1 ] && [ "$1" = "add" ]; then
echo "hg add with no arguments denied" 1>&2
false # sets exit code to 1, but doesn't close process like exit would
else
command hg $#
fi
}
Here is what it looks like in action after I source in the new function from my profile:
hg > /dev/null; echo $?
0
hg add > /dev/null; echo $?
hg add with no arguments denied
1
hg add . > /dev/null; echo $?
0
hg status
touch afile
hg add afile
hg status
A afile
You can undo a global add using the following command:
hg forget $(hg status -an)
Here, hg status -an will list all added files. hg forget will then remove those files from the list of added files.
You can also create an alias for this in your .hgrc, e.g.:
[alias]
unadd = !$HG forget $($HG status -an)
Note that this will also delist all previously added files that you did mean to add, so you may have to redo that.
Also, operating systems and shells have limits for how many arguments can be passed to a command. If you run into this limit because you accidentally added more than a few thousand files, you can use xargs instead:
hg status -an | xargs hg forget
Or, as an alias:
[alias]
unadd = !$HG status -an | xargs $HG forget

How do you check if a mercurial repo is in a clean state?

As a user, I usually use hg st to check the status of a repo, and verify that it is in a clean state, with no modified files.
Here I would like to do this programmatically. I know I can also use hg st for that, but the output is less than ideal for consumption by a computer program. Is there a better way to check whether a mercurial repo is in a clean state?
If you issue the hg identify --id command, it will suffix the ID with a + character when the repository has modified files. (Note: this flag does not report untracked files.)
If you grep the output of this command for the + character, you can use the exit status to determine whether there are modifications or no:
$ hg init
$ hg identify --id | grep --quiet + ; echo $?
1
$ touch a
$ hg identify --id | grep --quiet + ; echo $?
1
$ hg add a
$ hg identify --id | grep --quiet + ; echo $?
0
You should use hg summary:
$ hg init
$ echo blablabla > test.txt
$ hg summary
parent: -1:000000000000 tip (empty repository)
branch: default
commit: 1 unknown (clean)
update: (current)
Most major programming languages have HG APIs you can access.
This answer might be useful for other people searching this topic:
I agree to #SteveKayes comment above that hg status is a good command for programmatic consumption.
Here is an example how to use it in a bash script:
#!/bin/bash
set -e
cd /path/to/hg-repo
repo_status=`hg status | wc -l`
if [ $repo_status -ne 0 ]; then
echo "Repo is not clean"
else
echo "Repo is clean"
fi

logging mercurial transactions

this is a small addition to the previous script, and this time I would like to log details for the backup.
script /tmp/commit-push-log
# add all files to the repository
for REPOSITORY in $#
do
cd $REPOSITORY
# commit the changes
hg commit -A -m "Commit changes `date`"
# push the changes to the remote repository
if hg push
then
logger hg push completed without failure
else
logger hg push fails
fi
done
exit
cat /tmp/commit-push-log | logger
rm /tmp/commit-push-log
the problem is that i don't see any mercurial messages in the log. What can go wrong in my script?
You should not use static tmp filenames. Use mktemp, it's far safer.
You should cd "$REPOSITORY" instead of "cd $REPOSITORY" or things will get funny when REPOSITORY will contain any spaces or special characters.
You should not write automated commit comments. See here for the great article on this topic.
hg probably outputs errors to stderr. Use hg commit -A -m "$comment" 2>&1 and hg push 2>&1
my current version
for REPOSITORY in $#
do
# new temp file
OUTPUT_LOG=`tempfile`
echo -n > $OUTPUT_LOG
# checks whether $REPO is a repo
if [ ! -d $REPOSITORY/.hg ]; then
echo "Not a repository: $REPOSITORY"
exit 1;
fi
# change to that dir
cd "$REPOSITORY"
logger "Repository: $REPOSITORY"
# commit the changes
hg commit -A -m "Commit changes `date`" 2>&1 >> $OUTPUT_LOG
# push the changes to the remote repository
if hg push 2>&1 >> $OUTPUT_LOG
then
logger hg push completed without failure
else
logger hg push fails
exit 1;
fi
# log the contents and delete the tempfile
cat $OUTPUT_LOG | logger
rm -f $OUTLOG_LOG
done
exit 0