mercurial ignore creation/modyfication date change on LInux - linux

On Windows Mercurial ignores creation/modyfication time of file, as long as file itself didn't change. Linux can't apparently do that. In my job some people work on Windows and some on Linux machines and we have a lot of false-positive changes in mercurial.
Good example is when we regenerate Doctrine models from YML file. Most of them stay the same, changes are in one or two, but all get regenerated and I have to go through all of them and make sure, that it is safe to ignore their changes (revert) so they won't mess up mercurial commit.
Is there a way to make Linux see those files as Windows does?
By the way: I have checked and it is not related to EOL problem or UTF-8 BOM or other hidden characters. Only timestamps changes.
Thanks in advance!

Well, Mercurial on Linux does not commit a file if the mtime is the only change either :
~ $ mkdir test
~ $ cd test/
~/test $ hg init
~/test $ echo a > a
~/test $ ls -l
total 4
-rw------- 1 user users 2 Jul 23 13:21 a
~/test $ hg add a
adding a
~/test $ hg commit -m "Adding a"
a
committed changeset 0:e7d3dddff169
~/test $ ls -l
total 4
-rw------- 1 user users 2 Jul 23 13:21 a
~/test $ touch a
~/test $ ls -l
total 4
-rw------- 1 user users 2 Jul 23 13:22 a
~/test $ hg status
~/test $ hg commit -m "Mtime changed on a" a
nothing changed
~/test $
It does not detect a change if the ctime is altered either :
~/test $ ls -l
total 4
-rw------- 1 user users 2 Jul 23 13:22 a
~/test $ rm a
rm: remove regular file ‘a’? y
~/test $ echo a > a
~/test $ ls -l
total 4
-rw------- 1 user users 2 Jul 23 14:27 a
~/test $ hg status
~/test $ hg commit -m "Ctime changed on a" a
nothing changed
~/test $

Consequence of the comments for Remi's answer
You have real troubles with EOL in cross-platform development
Single possible and best friend for team in this situation is EOL Extension, which have to be enabled and used by all developers at the same time
Ignore "this is considered a feature of last resort" warning - you haven't another good way, and because "...if external forces dictate that these features are mandatory for using Mercurial, they're available..."
Read description of extension carefully, pay special attention to topic, titled with IMPORTANT in text (otherwise you'll get a lot of additional headache in addition to old)
Configure extension properly for your use-case
I heard about screaming, crying and tantrums, this extension related, from Windows users mostly, bad never had chances to use it in own real work (I'm Winboy and communicate with Winboys)

Related

fatal: Not a git repository: '.'

I have a valid git repository named /tmp/A.
When I cd to the /tmp/A and run any git command from bash it works good, but when I run git commands from callCommand call in haskell programm I get error:
fatal: Not a git repository: '.'
If I run in callCommand pwd and ls -la before git command, like:
callCommand $ "pwd; ls -la; git status"
It shows that it is at right path /tmp/A and ls shows that repository exists and has .git directory, but git returns error.
What wrong I do?
Upd.
ls output is
drwxrwxr-x 11 xxx xxx 4096 Mar 22 11:44 .
drwxrwxr-x 3 xxx xxx 4096 Mar 22 11:44 ..
drwxrwxr-x 8 xxx xxx 4096 Mar 22 11:44 .git
-rw-rw-r-- 1 xxx xxx 270 Mar 22 11:44 .gitignore
drwxrwxr-x 7 xxx xxx 4096 Mar 22 11:44 dir2
drwxrwxr-x 8 xxx xxx 4096 Mar 22 11:44 dir1
drwxrwxr-x 9 xxx xxx 4096 Mar 22 11:44 test
Upd. Upd.
Program which fails is called from hook post-receive of cloned git repository. When run same program not from hook of this repository, it works fine.
Why self cloning repository from hook does not works?
TL;DR: you probably want unset GIT_DIR at the front of your script (well, however Haskell spells this operation).
The issue here is that while /tmp/A is a sensible Git repository, the actual repository itself is in the .git sub-directory. That is, /tmp/A/ is the work-tree and /tmp/A/.git is the repository proper.
In normal operation, we run git subcommand arguments ..., e.g., git status or git commit -m message from our work-trees. The work-tree contains a .git directory or, in some cases,1 a .git file. The top-level git command checks for .git, finds it, and says aha, the repository is ./.git. Or, it does not find .git, so it looks one level up—e.g., from /tmp/A it would climb one level to /tmp itself, and check there for .git. This repeats until some sort of stopping point.2
In all cases, this search process must either stop successfully—by finding the repository proper—or else git subcommand dies with the fatal: Not a git repository ... message. Now comes the critical, and hidden in plain sight, secret: At this point, the top-level git command sets an environment variable named GIT_DIR to contain the path name of the actual repository. It then runs the sub-command, which uses $GIT_DIR to locate the repository. In our normal use-case, where we are in /tmp/A and /tmp/A contains a .git directory, this sets $GIT_DIR to /tmp/A/.git and the sub-commands all work.
But in your case, $GIT_DIR is already set. Specifially, it's set to .. So now the top-level git command stops searching. It just verifies that $GIT_DIR is valid and names a Git repository, or dies with the fatal error message. Since /tmp/A isn't a repository—it's really /tmp/A/.git—this causes the problem.
Unsetting the environment variable turns the search back on, fixing the problem. You can also use --git-dir as an argument, or set a correct value in $GIT_DIR. Note that the same rules apply with $GIT_WORK_TREE: the --work-tree argument sets $GIT_WORK_TREE, and if you don't use that and $GIT_WORK_TREE isn't set, the front-end git command uses its climb up the file system tree to a .git directory or file code to find the root of your work-tree. So if $GIT_DIR or $GIT_WORK_TREE are set when you run git subcommand, Git obeys them unless you override them with --git-dir and/or --work-tree.
Hooks always have $GIT_DIR set. They may or may not have $GIT_WORK_TREE set as well. Most of them run in the top level of the work-tree, but, as the githooks documentation notes, pre-receive, update, post-receive, post-update, and push-to-checkout all run in $GIT_DIR.
1The .git-as-a-file trick is used by both submodules and added work-trees, in modern Git. Git 1.7 and early 1.8 left submodules with embedded .git directories, and does not support added work-trees.
2The obvious stopping point is upon reaching /, when there is nowhere left to climb. However, Git is by default careful, at least on Unix and Unix-like systems, to avoid climbing through a mount point. Mount points allow you to graft different file system layers and/or storage pools into a single tree-structured hierarchy. Typically /tmp itself might be a memory file system, for instance, and large systems might isolate "system storage" (/ and the like) from "user storage" (/home). Docker uses mount points to restructure file systems in the docker image, and so on.

Where can I get the description of `--shared` option of `git init` command for Windows?

I am reading the Git documentation about the git init command:
--shared[=(false|true|umask|group|all|world|everybody|0xxx)] Specify that the Git repository is to be shared amongst several users. This
allows users belonging to the same group to push into that repository.
When specified, the config variable "core.sharedRepository" is set so
that files and directories under $GIT_DIR are created with the
requested permissions. When not specified, Git will use permissions
reported by umask(2).
The option can have the following values, defaulting to group if no
value is given:
umask (or false) Use permissions reported by umask(2). The default,
when --shared is not specified.
group (or true) Make the repository group-writable, (and g+sx, since
the git group may be not the primary group of all users). This is used
to loosen the permissions of an otherwise safe umask(2) value. Note
that the umask still applies to the other permission bits (e.g. if
umask is 0022, using group will not remove read privileges from other
(non-group) users). See 0xxx for how to exactly specify the repository
permissions.
all (or world or everybody) Same as group, but make the repository
readable by all users.
0xxx 0xxx is an octal number and each file will have mode 0xxx. 0xxx
will override users' umask(2) value (and not only loosen permissions
as group and all does). 0640 will create a repository which is
group-readable, but not group-writable or accessible to others. 0660
will create a repo that is readable and writable to the current user
and group, but inaccessible to others.
This information is for Linux-based OS only. Am I right? But what about Windows? I use Git for Windows. Windows uses ACL instead of umask for working with permissions. :(
It is very sad, but umask and --shared do nothing in the Git Bash for Windows:
Developer#BUSHCOMP MINGW64 /d/temp/000
$ ls -l readme.txt
-rw-r--r-- 1 Developer Domain users 0 Sep 10 16:44 readme.txt
Developer#BUSHCOMP MINGW64 /d/temp/000
$ chmod a+rw readme.txt
Developer#BUSHCOMP MINGW64 /d/temp/000
$ ls -l readme.txt
-rw-r--r-- 1 Developer Domain users 0 Sep 10 16:44 readme.txt
Permissions of the readme.txt wasn't changed: I see -rw-r--r-- instead of -rw-rw-rw-.
Developer#BUSHCOMP MINGW64 /d/temp/000
$ chmod 666 readme.txt
Developer#BUSHCOMP MINGW64 /d/temp/000
$ ls -l readme.txt
-rw-r--r-- 1 Developer Domain users 0 Sep 10 16:44 readme.txt
Permissions of the readme.txt wasn't changed again: I see -rw-r--r-- instead of -rw-rw-rw-.
Ok, I try to use --shared=0666:
Developer#BUSHCOMP MINGW64 /d/temp/000/111
$ git init --shared=0666
Bare repository is initialized Git в D:/temp/000/111/.git/
Developer#BUSHCOMP MINGW64 /d/temp/000/111 (master)
$ echo 2>test.txt
Developer#BUSHCOMP MINGW64 /d/temp/000/111 (master)
$ git add test.txt
Developer#BUSHCOMP MINGW64 /d/temp/000/111 (master)
$ git commit -m "Test"
[master (root commit) 0d01d64] Test
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.txt
Developer#BUSHCOMP MINGW64 /d/temp/000/111 (master)
$ ls -l test.txt
-rw-r--r-- 1 Developer Domain users 0 Sep 10 17:10 test.txt
At this case I see `-rw-r--r--` instead of `-rw-rw-rw-` also.
I've updated Git for Windows from 2.4.5 to 2.5.2 but these problems exist stil.
UPD
I got the answer here.

Can't write on hard drive owned by user and with permissions to write, read and execute

I am very puzzled by this problem I am having. I am trying to execute a file in Ubuntu 12.04 LTS via command line. I have a script that calls a program to run and write the results in a hard drive. I changed the permissions and ownership of everything to be wxr. Here is the ls -l of my script (called TEST-star):
-rwxrwxrwx 1 root root 950 Nov 15 13:16 TEST-star
Here is the ls -l of the package my script calls:
-rwxrwxrwx 1 root root 1931414 Nov 10 12:37 STAR
Finally the ls -l of the hard drive mounted in /media/CLC"
drwxrwxrwx 1 root root 8192 Nov 15 13:04 CLC
I have been trying to run it since yesterday and always get a message that I don't have permission to write the results:
EXITING because of FATAL ERROR: could not create output file ./_STARtmp//Unmapped.out.mate1.thread14
Solution: check that you have permission to write this file
I thought if I change the permissions to rwx and run my script as root it would not have a problem (using sudo). Right now I run out of options. Any suggestion would be appreciated. Please let me know what other information you would need solve this issue.
Thank you.
Here is the first line of script I am trying to run:
#!/bin/sh
cd /media/CLC/ANOPHELES-STAR-v2.4f1/; mkdir GambFemAnt1 && cd GambFemAnt1; echo $PWD && echo Starting mapping of GambFemAnt1; /home/aedes/Documents/STAR_2.4.0f1/STAR --genomeDir /media/Galaxy/Galaxy_data/Anopheles/STAR/Genome --readFilesIn /media/Galaxy/Galaxy_data/Anopheles/QC/GambFemAnt1/GambFemAnt1.fastq --runThreadN 23 --outFilterMismatchNmax 4 --outFilterMatchNminOverLread 0.75 --seedSearchLmax 30 --seedSearchStartLmax 30 --seedPerReadNmax 100000 --seedPerWindowNmax 100 --alignTranscriptsPerReadNmax 100000 --alignTranscriptsPerWindowNmax 10000 --outSAMstrandField intronMotif --outFilterIntronMotifs RemoveNoncanonical --outSAMtype BAM SortedByCoordinate --outReadsUnmapped Fastx; mv Aligned.sortedByCoord.out.bam GambFemAnt1.bam; mv Unmapped.out.mate1 GambFemAnt1-unmapped.fastq; cp *.fastq /media/CLC/ANOPHELES-STAR-v2.4f1/UNMAPED-reads/; cd /media/CLC/ANOPHELES-STAR-v2.4f1 && echo $PWD && echo GambFemAnt1 mapping finished;
I also posted a question for the authors of the package.
Turns out all the permissions were set correctly. The problem resigns within the package. I found out that it works using --runThreadN 12 instead of --runThreadN 23.

'git clone' respects umask, except for top level project directory

I would like to clone a git project (from github, say), and have the top level directory be writable by group.
I tried a couple different things. First, just setting the umask before cloning.
$ umask
0002
Files that I create are then writable by group
$ touch test
$ ls -l test
-rw-rw-r-- 1 user group 0 2012-05-17 09:32 test
Now I try git clone
$ git clone git#github.com:user/repo.git
Cloning into repo... [succeeds]
But the clone directory not writable by group.
$ ls -ld repo
drwxr-xr-x 11 user group 4096 2012-05-17 09:32 repo
I tried the same thing with a repo created with git init --shared=umask (which should already be the default) in a directory with 775 permissions. After pushing to github git clone gets the same results.
This isn't a huge deal, I can chmod in my checkout scripts. But if there's a right/builtin way to do this, that's preferable. Git is version 1.7.4.1 on Ubuntu 11.04.
Any ideas or links are appreciated. I saw this post, but it uses chmod, I haven't been able to find much else on this. Thanks!
Try setting the global "core.sharedRepository=group" just for the clone command:
git -c "core.sharedRepository=group" clone git#github.com:user/repo.git
ls -ld repo/.git
drwxrwsr-x 8 user user 4096 Jul 4 22:16 repo/.git/
This was due to a bug, fixed in git >= v1.7.11.3
See:
https://github.com/git/git/commit/45d4fdc2dc74c657a9c2e95bf04aed539fdcb0a4

Change Default Group in Script

Is it possible to change a user's default group inside a script for the duration of that script's execution?
I need to generate files in a script that have the proper user and group but my user's primary group is not who should own the resultant output.
$ groups
groupa groupb
$ ./myscript.sh
$ ls -l
-rw-r--r-- 1 me groupa 0 Sep 17 09:42 myscript_output.txt
But I want "groupb".
myscript.sh:
#!/bin/bash
touch "myscript_output.txt"
Try the newgrp command, which changes the primary group of a user into another group of which that user is a member:
#!/bin/bash
newgrp groupb << END
touch "myscript_output.txt"
END
The sg command can do this pretty well.
#!/bin/bash
sg groupb "touch myscript-output.txt"
The group can be set from a script. It only requires the "if"
statement below. The group is checked and if it is incorrect, then
the script is restarted with the sg command Nate mentioned.
A check for looping is employed(just in case the unforeseeable happens.)
To use, just change the group from "wheel" to the desired. Replace the "DEMO" section with the regular code.
Read on, below(after the script.)
#! /bin/sh
#
# If the group(set with NEEDGRP) is already correct, or this code has already
# run, then this section is skipped and the rest of the
# script is run; otherwise sg is called to restart the script with the
# desired group. Assumes the command "id -ng" returns the group.
if ! [ "${SBREADY:=false}" = true -o $(id -ng) = ${NEEDGRP:=wheel} ] ; then
export SBREADY=true
exec sg $NEEDGRP "$0" "$#"
fi
# ---------------------- DEMO: CUT HERE ---------------------------
# This is a demonstration of creating files.
echo HELLO my group is $(id -ng), GID=$(id -g)
# NOTE: files are created with the current group only if the directory
# is not sgid.
# Show current directory and permissions on it
echo
pwd -P
ls -ld .
echo
# Create and list some new files, the remove them.
touch my-$$.{a,b,c}
echo Created my-$$.{a,b,c}...
ls -l my-$$.{a,b,c}
echo
rm -v my-$$.{a,b,c}
Following are printouts of some tests run in order to explain why just changing groups my not be sufficient to ensure files have the right group ownership. Directory permissions also come into play.
This first log is the output from ruining in a regular directory. The script is run as user frayser, and group frayser. Files are created
with the desired group. Compare to the next listing:
frayser#gentoo ~/src/Answers $ (cd /tmp; $OLDPWD/set-group.sh)
HELLO my group is wheel, GID=10
/tmp
drwxrwxrwt 16 root root 976 Sep 24 04:45 .
Created my-19201.a... my-19201.b... my-19201.c...
-rw-r----- 1 frayser wheel 0 Sep 24 04:53 my-19201.a
-rw-r----- 1 frayser wheel 0 Sep 24 04:53 my-19201.b
-rw-r----- 1 frayser wheel 0 Sep 24 04:53 my-19201.c
removed `my-19201.a'
removed `my-19201.b'
removed `my-19201.c'
Now this next run happens in a director that is sgid "conman" because as a policy, Configuration Management is given group ownership of all src directories.
NOTE: The files inherit the group of the directory.
frayser#gentoo ~/src/Answers $ ./set-group.sh
HELLO my group is wheel, GID=10
/usr/lucho/src/frayser/practice
drwxr-s--- 6 frayser conman 768 Sep 24 04:51 .
Created my-19214.a... my-19214.b... my-19214.c...
-rw-r----- 1 frayser conman 0 Sep 24 04:54 my-19214.a
-rw-r----- 1 frayser conman 0 Sep 24 04:54 my-19214.b
-rw-r----- 1 frayser conman 0 Sep 24 04:54 my-19214.c
removed `my-19214.a'
removed `my-19214.b'
removed `my-19214.c'
frayser#gentoo ~/src/Answers $
Because of directory permissions, it may be necessary for a script to
explicitly set permissions and ownership.
Normally that can be accomplished by applying to a program the modifications:
chgrp groupb myprog
chmod g+s myprog
But that works with normal programs - not with the shell scripts (for security reasons). For a shell script there is no other way (at least I'm not aware (*)) other than from inside script itself to call the chgrp:
#!/bin/bash
FNAME="myscript_output.txt"
GRP=groupb
touch $FNAME
chgrp $GRP $FNAME || { echo 2>&1 "Can't change group of $FNAME to $GRP"; exit 1; }
(*) Some people for the purpose write a tiny wrapper C program. But that is kludgy. Search net for "setuid shell scripts" - there would be lots of such example C programs and replace most commonly found there setuid(0) with getgrnam() + setgid().

Resources