* Re: [Q] Determing if a commit is reachable from the HEAD ?
From: Sitaram Chamarty @ 2012-01-20 22:50 UTC (permalink / raw)
To: Brian Foster; +Cc: git mailing list
In-Reply-To: <201201201433.30267.brian.foster@maxim-ic.com>
On Fri, Jan 20, 2012 at 7:03 PM, Brian Foster <brian.foster@maxim-ic.com> wrote:
>
> Hello,
>
> Whilst I have found answers to my question on the Web,
> only one seems to do exactly what I want ....
>
> x---Y---y---y---y HEAD
> /
> ...--o---o---C---o---S
> \
> n---n---N---*---* other
>
> In a script, how can I determine commit Y is reachable
> from the current HEAD ? And, much more importantly
I've been using 'git rev-list HEAD..Y'. If it produces any output, Y
is not reachable from HEAD (there is something in Y that is not in
HEAD).
^ permalink raw reply
* Re: [Q] Determing if a commit is reachable from the HEAD ?
From: David Brown @ 2012-01-20 23:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Andreas Schwab, Brian Foster, git mailing list
In-Reply-To: <7v7h0mfahx.fsf@alter.siamese.dyndns.org>
On Fri, Jan 20, 2012 at 11:18:50AM -0800, Junio C Hamano wrote:
> David Brown <davidb@codeaurora.org> writes:
>
> > On Fri, Jan 20, 2012 at 03:13:58PM +0100, Andreas Schwab wrote:
> >> Brian Foster <brian.foster@maxim-ic.com> writes:
> >>
> >> > In a script, how can I determine commit Y is reachable
> >> > from the current HEAD ?
> >>
> >> test $(git merge-base HEAD Y) = $(git rev-parse Y)
> >
> > Almost. It works as long as there is only one merge base. You really
> > need to check if $(git rev-parse Y) is one of $(git merge-base --all
> > HEAD Y)
>
> Can you give us an example of a topology to which "merge-base --all HEAD Y"
> gives more than one output and Y is still reachable from HEAD?
>
> It is my understanding that merge-base computation will give only Y and
> nothing else when Y is reachable from HEAD. I also think this assumption
> is used by some of the internal code in Git, and that is why I care.
Hmm, I thought I'd convinced myself that this was possible. Now, I
can't come up with a way of doing it that doesn't involve improper
commits with earlier timestamps than their parents.
Sorry about that,
David
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply
* Re: [Q] Determing if a commit is reachable from the HEAD ?
From: Junio C Hamano @ 2012-01-21 0:04 UTC (permalink / raw)
To: David Brown; +Cc: Andreas Schwab, Brian Foster, git mailing list
In-Reply-To: <20120120233335.GA20302@codeaurora.org>
David Brown <davidb@codeaurora.org> writes:
> Hmm, I thought I'd convinced myself that this was possible. Now, I
> can't come up with a way of doing it that doesn't involve improper
> commits with earlier timestamps than their parents.
I'd actually want to see a way to do so that *does* involve timestamp
skew.
^ permalink raw reply
* highlights from next "What's cooking"
From: Junio C Hamano @ 2012-01-21 0:13 UTC (permalink / raw)
To: git
These have been merged for upcoming 1.7.9 recently:
* jc/pull-signed-tag-doc (2012-01-17) 1 commit
+ pulling signed tag: add howto document
* mh/maint-show-ref-doc (2012-01-13) 2 commits
(merged to 'next' on 2012-01-16 at 8573f09)
+ git-show-ref doc: typeset regexp in fixed width font
+ git-show-ref: fix escaping in asciidoc source
* nd/pathspec-recursion-cleanup (2012-01-16) 2 commits
(merged to 'next' on 2012-01-16 at 0189264)
+ diff-index: enable recursive pathspec matching in unpack_trees
+ Document limited recursion pathspec matching with wildcards
* tr/maint-word-diff-incomplete-line (2012-01-12) 1 commit
(merged to 'next' on 2012-01-16 at 58ddaaf)
+ word-diff: ignore '\ No newline at eof' marker
* jk/credentials (2012-01-16) 4 commits
(merged to 'next' on 2012-01-16 at 2810b82)
+ credential-cache: ignore "connection refused" errors
(merged to 'next' on 2012-01-16 at 1c6c94a)
+ unix-socket: do not let close() or chdir() clobber errno during cleanup
+ credential-cache: report more daemon connection errors
+ unix-socket: handle long socket pathnames
Also I updated the jc/pull-signed-tag topic that follows Linus's
suggestion to always spawn an editor when running "git merge" in an
interactive session. The special-case environment variable has been
renamed to MERGE_AUTOEDIT, and scripts can set it to "no" when they start
to accept the autogenerated merge log message. There is no plan to
encourage humans to keep using the historical behaviour, hence there is no
support for configuration variable (e.g. merge.autoedit) that can be set
to 'no'.
^ permalink raw reply
* Re: post-update to stash after push to non-bare current branch
From: Neal Kreitzinger @ 2012-01-21 0:13 UTC (permalink / raw)
Cc: Neal Kreitzinger, git
In-Reply-To: <4F188FA2.1000209@gmail.com>
On 1/19/2012 3:48 PM, Neal Kreitzinger wrote:
> On 1/18/2012 7:00 PM, Junio C Hamano wrote:
>> Neal Kreitzinger<nkreitzinger@gmail.com> writes:
>>
>>>> Have you checked where in the filesystem hierarchy that script
>>>> is run (hint: pwd)?
>>>>
>>> echo pwd in post-update echoes /path/WORKTREE/.git in git-push
>>> stdout. ... 'git-checkout -f' works manually, but in post-update
>>> hook...
>>
>> Stronger hint. Did you run "git checkout -f" in
>> /path/WORKTREE/.git to back that "works manually" claim?
>
> (Manual behavior): If pwd is WORKTREE/ then git-checkout has correct
> effect, ie. worktree, index, and HEAD match. If pwd is
> WORKTREE/.git/ then git-checkout complains 'must be run in a
> worktree' and has no effect.
>
> (post-update hook behavior): If pwd is WORKTREE/.git/ then git-push
> verbage does not complain, and git-checkout exits zero status but
> has incorrect effect, ie. index and HEAD match, but worktree matches
> HEAD@{1}. If pwd is WORKTREE/ then git-push complains 'not a git
> repository', and git-checkout exits non-zero status and has no
> effect, ie. worktree and index match HEAD@{1}.
>
> Evidence:
>
> (post-update hook script): MYPWD=`pwd` echo $MYPWD pushd
> /home/neal/FSNMSTHTML MYPWD=`pwd` echo $MYPWD git checkout -f HEAD
> if [ $? -ne 0 ]; then echo "error on checkout!" else echo "checkout
> HEAD to non-bare remote current branch after push" fi echo $MYPWD
> popd MYPWD=`pwd` echo $MYPWD
>
> (git-push verbage): $ git push origin HEAD Counting objects: 9, done.
> Delta compression using up to 8 threads. Compressing objects: 100%
> (5/5), done. Writing objects: 100% (5/5), 462 bytes, done. Total 5
> (delta 4), reused 0 (delta 0) Unpacking objects: 100% (5/5), done.
> remote: warning: updating the current branch remote:
> /home/neal/FSNMSTHTML/.git remote: ~/FSNMSTHTML ~/FSNMSTHTML/.git
> remote: /home/neal/FSNMSTHTML remote: fatal: Not a git repository:
> '.' remote: error on checkout! remote: /home/neal/FSNMSTHTML remote:
> ~/FSNMSTHTML/.git remote: /home/neal/FSNMSTHTML/.git To
> file:///home/neal/FSNMSTHTML cee9269..34dc5a9 HEAD -> master
>
To get this to work I had to learn more about shell scripting and export
the GIT_WORK_TREE git environment variable.
(post-update hook):
export GIT_WORK_TREE=/home/neal/FSNMSTHTML
git checkout -f HEAD
for more info see this stackoverflow thread
http://stackoverflow.com/questions/6635018/reuse-git-work-tree-in-post-receive-hook-to-rm-a-few-files
v/r,
neal
^ permalink raw reply
* Re: post-update to stash after push to non-bare current branch
From: Junio C Hamano @ 2012-01-21 0:16 UTC (permalink / raw)
To: Neal Kreitzinger
In-Reply-To: <4F1A0311.30502@gmail.com>
Neal Kreitzinger <nkreitzinger@gmail.com> writes:
> To get this to work I had to learn more about shell scripting and export
> the GIT_WORK_TREE git environment variable.
>
> (post-update hook):
> export GIT_WORK_TREE=/home/neal/FSNMSTHTML
> git checkout -f HEAD
Hmm, I thought "cd .. && git checkout -f HEAD" (or "git reset --hard")
would have worked.
^ permalink raw reply
* [PATCH v2 1/3] git-p4: Add checkpoint() task
From: Vitor Antunes @ 2012-01-21 0:21 UTC (permalink / raw)
To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes
In-Reply-To: <1327105292-30092-1-git-send-email-vitor.hda@gmail.com>
Signed-off-by: Vitor Antunes <vitor.hda@gmail.com>
---
contrib/fast-import/git-p4 | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 3e1aa27..417d119 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -1450,6 +1450,14 @@ class P4Sync(Command, P4UserMap):
.replace("%25", "%")
return path
+ # Force a checkpoint in fast-import and wait for it to finish
+ def checkpoint(self):
+ self.gitStream.write("checkpoint\n\n")
+ self.gitStream.write("progress checkpoint\n\n")
+ out = self.gitOutput.readline()
+ if self.verbose:
+ print "checkpoint finished: " + out
+
def extractFilesFromCommit(self, commit):
self.cloneExclude = [re.sub(r"\.\.\.$", "", path)
for path in self.cloneExclude]
--
1.7.7.rc2.14.g5e044.dirty
^ permalink raw reply related
* [PATCH v2 0/3] git-p4: Search for parent commit on branch creation
From: Vitor Antunes @ 2012-01-21 0:21 UTC (permalink / raw)
To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes
The new version of these patches includes the improvement suggestions
from Pete Wyckoff:
- Use os.path.join().
- Use git update-ref -d to remove refs.
- Read $GIT_DIR environment variable.
- Optimize comparison cycle to avoid excessive use of checkpoint
command.
Vitor Antunes (3):
git-p4: Add checkpoint() task
git-p4: Search for parent commit on branch creation
git-p4: Add test case for complex branch import
contrib/fast-import/git-p4 | 38 ++++++++++++++++++++-
t/t9801-git-p4-branch.sh | 80 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 1 deletions(-)
--
1.7.7.rc2.14.g5e044.dirty
^ permalink raw reply
* [PATCH v2 3/3] git-p4: Add test case for complex branch import
From: Vitor Antunes @ 2012-01-21 0:21 UTC (permalink / raw)
To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes
In-Reply-To: <1327105292-30092-1-git-send-email-vitor.hda@gmail.com>
Check if branches created from old changelists are correctly imported.
Signed-off-by: Vitor Antunes <vitor.hda@gmail.com>
---
t/t9801-git-p4-branch.sh | 80 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index a25f18d..ed4e48c 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -226,6 +226,86 @@ test_expect_success 'git-p4 clone simple branches' '
)
'
+# Create a complex branch structure in P4 depot to check if they are correctly
+# cloned. The branches are created from older changelists to check if git-p4 is
+# able to correctly detect them.
+# The final expected structure is:
+# `branch1
+# | `- file1
+# | `- file2 (updated)
+# | `- file3
+# `branch2
+# | `- file1
+# | `- file2
+# `branch3
+# | `- file1
+# | `- file2 (updated)
+# | `- file3
+# `branch4
+# | `- file1
+# | `- file2
+# `branch5
+# `- file1
+# `- file2
+# `- file3
+test_expect_success 'git-p4 add complex branches' '
+ test_when_finished cleanup_git &&
+ test_create_repo "$git" &&
+ (
+ cd "$cli" &&
+ changelist=$(p4 changes -m1 //depot/... | cut -d" " -f2) &&
+ changelist=$(($changelist - 5)) &&
+ p4 integrate //depot/branch1/...@$changelist //depot/branch4/... &&
+ p4 submit -d "branch4" &&
+ changelist=$(($changelist + 2)) &&
+ p4 integrate //depot/branch1/...@$changelist //depot/branch5/... &&
+ p4 submit -d "branch5"
+ )
+'
+
+# Configure branches through git-config and clone them. git-p4 will only be able
+# to clone the original structure if it is able to detect the origin changelist
+# of each branch.
+test_expect_success 'git-p4 clone complex branches' '
+ test_when_finished cleanup_git &&
+ test_create_repo "$git" &&
+ (
+ cd "$git" &&
+ git config git-p4.branchList branch1:branch2 &&
+ git config --add git-p4.branchList branch1:branch3 &&
+ git config --add git-p4.branchList branch1:branch4 &&
+ git config --add git-p4.branchList branch1:branch5 &&
+ "$GITP4" clone --dest=. --detect-branches //depot@all &&
+ git log --all --graph --decorate --stat &&
+ git reset --hard p4/depot/branch1 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_file file3 &&
+ grep -q update file2 &&
+ git reset --hard p4/depot/branch2 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_missing file3 &&
+ ! grep -q update file2 &&
+ git reset --hard p4/depot/branch3 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_file file3 &&
+ grep -q update file2 &&
+ git reset --hard p4/depot/branch4 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_missing file3 &&
+ ! grep -q update file2 &&
+ git reset --hard p4/depot/branch5 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_file file3 &&
+ ! grep -q update file2 &&
+ test_path_is_missing .git/git-p4-tmp
+ )
+'
+
test_expect_success 'kill p4d' '
kill_p4d
'
--
1.7.7.rc2.14.g5e044.dirty
^ permalink raw reply related
* [PATCH v2 2/3] git-p4: Search for parent commit on branch creation
From: Vitor Antunes @ 2012-01-21 0:21 UTC (permalink / raw)
To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes
In-Reply-To: <1327105292-30092-1-git-send-email-vitor.hda@gmail.com>
To find out which is its parent the commit of the new branch is applied
sequentially to each blob of the parent branch from the newest to the
oldest. The first blob which results in a zero diff is considered the
parent commit. If none is found, then the commit is applied to the top
of the parent branch.
A fast-import "checkpoint" call is required for each comparison because
diff-tree is only able to work with blobs on disk. But most of these
commits will not be part of the final imported tree, making fast-import
fail. To avoid this, the temporary branches are tracked and then removed
at the end of the import process.
Signed-off-by: Vitor Antunes <vitor.hda@gmail.com>
---
contrib/fast-import/git-p4 | 30 +++++++++++++++++++++++++++++-
1 files changed, 29 insertions(+), 1 deletions(-)
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 417d119..2e3b741 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -1429,6 +1429,8 @@ class P4Sync(Command, P4UserMap):
self.cloneExclude = []
self.useClientSpec = False
self.clientSpecDirs = None
+ self.tempBranches = []
+ self.tempBranchLocation = "git-p4-tmp"
if gitConfig("git-p4.syncFromOrigin") == "false":
self.syncWithOrigin = False
@@ -2012,7 +2014,27 @@ class P4Sync(Command, P4UserMap):
parent = self.initialParents[branch]
del self.initialParents[branch]
- self.commit(description, filesForCommit, branch, [branchPrefix], parent)
+ parentFound = False
+ if len(parent) > 0:
+ tempBranch = os.path.join(self.tempBranchLocation, "%d" % (change))
+ if self.verbose:
+ print "Creating temporary branch: " + tempBranch
+ self.commit(description, filesForCommit, tempBranch, [branchPrefix])
+ self.tempBranches.append(tempBranch)
+ self.checkpoint()
+ for blob in read_pipe_lines("git rev-list --reverse --no-merges %s" % parent):
+ blob = blob.strip()
+ if len( read_pipe("git diff-tree %s %s" % (blob, tempBranch)) ) == 0:
+ parentFound = True
+ if self.verbose:
+ print "Found parent of %s in commit %s" % (branch, blob)
+ break
+ if parentFound:
+ self.commit(description, filesForCommit, branch, [branchPrefix], blob)
+ else:
+ if self.verbose:
+ print "Parent of %s not found. Committing into head of %s" % (branch, parent)
+ self.commit(description, filesForCommit, branch, [branchPrefix], parent)
else:
files = self.extractFilesFromCommit(description)
self.commit(description, files, self.branch, self.depotPaths,
@@ -2347,6 +2369,12 @@ class P4Sync(Command, P4UserMap):
self.gitOutput.close()
self.gitError.close()
+ # Cleanup temporary branches created during import
+ if self.tempBranches != []:
+ for branch in self.tempBranches:
+ read_pipe("git update-ref -d %s" % branch)
+ os.rmdir(os.path.join(os.environ.get("GIT_DIR", ".git"), self.tempBranchLocation))
+
return True
class P4Rebase(Command):
--
1.7.7.rc2.14.g5e044.dirty
^ permalink raw reply related
* Re: post-update to stash after push to non-bare current branch
From: Neal Kreitzinger @ 2012-01-21 0:35 UTC (permalink / raw)
To: Junio C Hamano
In-Reply-To: <7vr4ytdi54.fsf@alter.siamese.dyndns.org>
On 1/20/2012 6:16 PM, Junio C Hamano wrote:
> Neal Kreitzinger<nkreitzinger@gmail.com> writes:
>
>> To get this to work I had to learn more about shell scripting and export
>> the GIT_WORK_TREE git environment variable.
>>
>> (post-update hook):
>> export GIT_WORK_TREE=/home/neal/FSNMSTHTML
>> git checkout -f HEAD
>
>
> Hmm, I thought "cd ..&& git checkout -f HEAD" (or "git reset --hard")
> would have worked.
Ok, I just tried that for the first time and it complained "not a git
repository: '.'" because it looks like that caused GIT_DIR to no longer
point to WORKTREE/.git but instead to WORKTREE/ because GIT_DIR is set
to '.' in the post-update script's environment as indicated in this
thread:
http://stackoverflow.com/questions/6635018/reuse-git-work-tree-in-post-receive-hook-to-rm-a-few-files
v/r,
neal
^ permalink raw reply
* Re: [PATCH v2 3/3] git-p4: Add test case for complex branch import
From: Junio C Hamano @ 2012-01-21 4:54 UTC (permalink / raw)
To: Vitor Antunes; +Cc: git, Pete Wyckoff, Luke Diamand
In-Reply-To: <1327105292-30092-4-git-send-email-vitor.hda@gmail.com>
Vitor Antunes <vitor.hda@gmail.com> writes:
> +test_expect_success 'git-p4 add complex branches' '
> + test_when_finished cleanup_git &&
> + test_create_repo "$git" &&
> + (
> + cd "$cli" &&
> + changelist=$(p4 changes -m1 //depot/... | cut -d" " -f2) &&
> + changelist=$(($changelist - 5)) &&
> + p4 integrate //depot/branch1/...@$changelist //depot/branch4/... &&
> + p4 submit -d "branch4" &&
> + changelist=$(($changelist + 2)) &&
> + p4 integrate //depot/branch1/...@$changelist //depot/branch5/... &&
> + p4 submit -d "branch5"
That's a strange quoting convention. Why are "branch4" and "branch5"
enclosed in double quotes while "integrate" and "submit" aren't?
(rhetorical: do not quote these branch names without a good reason).
> +# Configure branches through git-config and clone them. git-p4 will only be able
> +# to clone the original structure if it is able to detect the origin changelist
> +# of each branch.
> +test_expect_success 'git-p4 clone complex branches' '
> + test_when_finished cleanup_git &&
> + test_create_repo "$git" &&
> + (
> + cd "$git" &&
> + git config git-p4.branchList branch1:branch2 &&
> + git config --add git-p4.branchList branch1:branch3 &&
> + git config --add git-p4.branchList branch1:branch4 &&
> + git config --add git-p4.branchList branch1:branch5 &&
> + "$GITP4" clone --dest=. --detect-branches //depot@all &&
> + git log --all --graph --decorate --stat &&
> + git reset --hard p4/depot/branch1 &&
> + test_path_is_file file1 &&
> + test_path_is_file file2 &&
> + test_path_is_file file3 &&
> + grep -q update file2 &&
Do you really need to use "-q" here? Wouldn't it help if you wrote it
without it while debugging tests with "sh ./t9801-*.sh -v"?
Also how does this series interact with the series Luke posted earlier on
branches and labels?
Thanks.
^ permalink raw reply
* Re: [PATCH v2 2/3] git-p4: Search for parent commit on branch creation
From: Junio C Hamano @ 2012-01-21 4:55 UTC (permalink / raw)
To: Vitor Antunes; +Cc: git, Pete Wyckoff, Luke Diamand
In-Reply-To: <1327105292-30092-3-git-send-email-vitor.hda@gmail.com>
Vitor Antunes <vitor.hda@gmail.com> writes:
> A fast-import "checkpoint" call is required for each comparison because
> diff-tree is only able to work with blobs on disk. But most of these
> commits will not be part of the final imported tree, making fast-import
> fail. To avoid this, the temporary branches are tracked and then removed
> at the end of the import process.
>
> Signed-off-by: Vitor Antunes <vitor.hda@gmail.com>
> ---
It might make sense to squash 1/3 with this patch; the definition alone
without any actual user would not be very useful and won't help hunting
for breakages, if exists, in the future.
> @@ -2012,7 +2014,27 @@ class P4Sync(Command, P4UserMap):
> parent = self.initialParents[branch]
> del self.initialParents[branch]
>
> - self.commit(description, filesForCommit, branch, [branchPrefix], parent)
> + parentFound = False
> + if len(parent) > 0:
> + tempBranch = os.path.join(self.tempBranchLocation, "%d" % (change))
> + if self.verbose:
> + print "Creating temporary branch: " + tempBranch
> + self.commit(description, filesForCommit, tempBranch, [branchPrefix])
> + self.tempBranches.append(tempBranch)
> + self.checkpoint()
> + for blob in read_pipe_lines("git rev-list --reverse --no-merges %s" % parent):
> + blob = blob.strip()
> + if len( read_pipe("git diff-tree %s %s" % (blob, tempBranch)) ) == 0:
> + parentFound = True
> + if self.verbose:
> + print "Found parent of %s in commit %s" % (branch, blob)
... also this looks excessively deeply nested, which is a sign that it
might be a good idea to refactor this part into a separate helper function
or something.
^ permalink raw reply
* Re: [Q] Determing if a commit is reachable from the HEAD ?
From: David Brown @ 2012-01-21 4:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Andreas Schwab, Brian Foster, git mailing list
In-Reply-To: <7vzkdhdiot.fsf@alter.siamese.dyndns.org>
On Fri, Jan 20, 2012 at 04:04:50PM -0800, Junio C Hamano wrote:
> David Brown <davidb@codeaurora.org> writes:
>
> > Hmm, I thought I'd convinced myself that this was possible. Now, I
> > can't come up with a way of doing it that doesn't involve improper
> > commits with earlier timestamps than their parents.
>
> I'd actually want to see a way to do so that *does* involve timestamp
> skew.
Sorry, I guess I shouldn't tried this with a recent version of git. I
can't cause this, and it looks like there's some pretty sophisticated
stuff in there to deal with this.
David
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply
* [PATCH] mergetool: Suppress stderr and fix the "both added" test
From: David Aguilar @ 2012-01-21 10:26 UTC (permalink / raw)
To: gitster; +Cc: jcwenger, git
Silence error messages when "git checkout-index" is used to
checkout a stage that does not exist. This can happen now that
mergetool calls checkout_staged_file() unconditionally when
creating the temporary $BASE, $LOCAL, and $REMOTE files.
Fix the test so that it checks the contents of the "both added"
file. The test was passing as a consequence of accidentally
handing a bad path to "cat".
Signed-off-by: David Aguilar <davvid@gmail.com>
---
This applies on top of da/maint-mergetool-twoway in pu.
git-mergetool.sh | 4 +++-
t/t7610-mergetool.sh | 5 +++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/git-mergetool.sh b/git-mergetool.sh
index 24bedc5..a9f23f7 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -181,7 +181,9 @@ stage_submodule () {
}
checkout_staged_file () {
- tmpfile=$(expr "$(git checkout-index --temp --stage="$1" "$2")" : '\([^ ]*\) ')
+ tmpfile=$(expr \
+ "$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \
+ : '\([^ ]*\) ')
if test $? -eq 0 -a -n "$tmpfile" ; then
mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3"
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 2272743..3f261a3 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -465,8 +465,9 @@ test_expect_success 'directory vs modified submodule' '
test_expect_success 'file with no base' '
git checkout -b test13 branch1 &&
test_must_fail git merge master &&
- git mergetool --no-prompt --tool mybase -- base &&
- test "$(cat "$MERGED")" = "" &&
+ git mergetool --no-prompt --tool mybase -- both &&
+ >expected &&
+ test_cmp both expected &&
git reset --hard master >/dev/null 2>&1
'
--
1.7.7.166.g1cd0c
^ permalink raw reply related
* Re: [PATCH v2 3/3] git-p4: Add test case for complex branch import
From: Luke Diamand @ 2012-01-21 10:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Vitor Antunes, git, Pete Wyckoff
In-Reply-To: <7vehutd59p.fsf@alter.siamese.dyndns.org>
On 21/01/12 04:54, Junio C Hamano wrote:
> Vitor Antunes<vitor.hda@gmail.com> writes:
>
>> + grep -q update file2&&
>
> Do you really need to use "-q" here? Wouldn't it help if you wrote it
> without it while debugging tests with "sh ./t9801-*.sh -v"?
>
> Also how does this series interact with the series Luke posted earlier on
> branches and labels?
Vitor's series applies cleanly to my changes.
However, one thing I noticed in reading through is that it will break if
you end up importing a P4 branch that has spaces (or other shell chars)
in its name. A quick test confirms this.
- the code doesn't handle the names properly
- git and p4 have different ideas about valid branch names
But before rejecting Vitor's changes because of that it would be worth
considering whether we care (much). My own opinion is that if you have
developers who are daft enough to put spaces or dollars in their branch
names then their project is already doomed anyway....
Perhaps it would be enough just to issue a warning ("your project is
doomed; start working on your CV") and skip such branch names rather
than falling over with inexplicable error messages.
>
> Thanks.
^ permalink raw reply
* How to restore "svn mirror generator"?
From: Manuel Reimer @ 2012-01-21 15:45 UTC (permalink / raw)
To: git
Hello,
I want to create a GIT mirror of a SVN repository.
I plan to mirror a SVN server to GIT. I don't want to fetch the full history but
all future commits should be mirrored.
I plan to do this in the following way:
git svn clone -r $REVISION_TO_START_WITH http://domain.tld/path/to/svn
git remote add origin ssh://user@gitserver.tld/mirror.git
git push
Now, from time to time, I want to update with
git svn rebase
git push
I hope, so far I'm on the right way.
But what happens if, for some reason, my local repository gets lost?
How to reconnect GIT and SVN so I'm able to mirror, again?
Is the first step to clone the GIT repository and then, somehow, get the SVN
connected, again, or do I have to do it the other way around?
Yours
Manuel
^ permalink raw reply
* Re: [PATCH v2 3/3] git-p4: Add test case for complex branch import
From: Pete Wyckoff @ 2012-01-21 17:11 UTC (permalink / raw)
To: Luke Diamand; +Cc: Junio C Hamano, Vitor Antunes, git
In-Reply-To: <4F1A98A3.2090607@diamand.org>
luke@diamand.org wrote on Sat, 21 Jan 2012 10:51 +0000:
> On 21/01/12 04:54, Junio C Hamano wrote:
> >Vitor Antunes<vitor.hda@gmail.com> writes:
> >
> >>+ grep -q update file2&&
> >
> >Do you really need to use "-q" here? Wouldn't it help if you wrote it
> >without it while debugging tests with "sh ./t9801-*.sh -v"?
> >
> >Also how does this series interact with the series Luke posted earlier on
> >branches and labels?
>
> Vitor's series applies cleanly to my changes.
>
> However, one thing I noticed in reading through is that it will
> break if you end up importing a P4 branch that has spaces (or other
> shell chars) in its name. A quick test confirms this.
>
> - the code doesn't handle the names properly
> - git and p4 have different ideas about valid branch names
>
> But before rejecting Vitor's changes because of that it would be
> worth considering whether we care (much). My own opinion is that if
> you have developers who are daft enough to put spaces or dollars in
> their branch names then their project is already doomed anyway....
>
> Perhaps it would be enough just to issue a warning ("your project is
> doomed; start working on your CV") and skip such branch names rather
> than falling over with inexplicable error messages.
This doesn't seem like a big deal. The read_pipe and
read_pipe_lines calls shoud be list-ified. That gets rid
of the problem with shell interactions.
For git branch name reserved characters, a little function
to replace the bogus characters with "_" would avoid needing
to go work on the resume. Anything in bad_ref_char() and
check_refname_component(). I agree this doesn't have to be
perfect.
This could be a new patch unrelated to Vitor's series, which
verifies branch names anywhere a new commit is made.
-- Pete
^ permalink raw reply
* [PATCH] optionally deny all pushes
From: Clemens Buchacher @ 2012-01-21 17:49 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
For a mirror repository which is updated only by pulling from upstream,
it is convenient to disallow all pushes. An accidental push from a
downstream repository would mess up the mirror's state as well as future
updates.
Add a boolean configuration variable receive.denyAll. If enabled,
receive-pack will deny all ref updates.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
---
Documentation/config.txt | 4 ++++
Documentation/git-push.txt | 1 +
builtin/receive-pack.c | 11 +++++++++++
contrib/completion/git-completion.bash | 1 +
t/t5400-send-pack.sh | 17 +++++++++++++++++
t/t5516-fetch-push.sh | 12 ++++++++++++
6 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 04f5e19..edbddea 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1683,6 +1683,10 @@ receive.unpackLimit::
especially on slow filesystems. If not set, the value of
`transfer.unpackLimit` is used instead.
+receive.denyAll::
+ If set to true, git-receive-pack will deny all ref updates.
+ The repository can not be updated remotely.
+
receive.denyDeletes::
If set to true, git-receive-pack will deny a ref update that deletes
the ref. Use this to prevent such a ref deletion via a push.
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index aede488..7c6cc63 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -219,6 +219,7 @@ remote rejected::
The remote end refused the update. Usually caused by a hook
on the remote side, or because the remote repository has one
of the following safety options in effect:
+ `receive.denyAll` (for all pushes),
`receive.denyCurrentBranch` (for pushes to the checked out
branch), `receive.denyNonFastForwards` (for forced
non-fast-forward updates), `receive.denyDeletes` or
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index d2dcb7e..9cd04f9 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -22,6 +22,7 @@ enum deny_action {
DENY_REFUSE
};
+static int deny_all;
static int deny_deletes;
static int deny_non_fast_forwards;
static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
@@ -57,6 +58,11 @@ static enum deny_action parse_deny_action(const char *var, const char *value)
static int receive_pack_config(const char *var, const char *value, void *cb)
{
+ if (strcmp(var, "receive.denyall") == 0) {
+ deny_all = git_config_bool(var, value);
+ return 0;
+ }
+
if (strcmp(var, "receive.denydeletes") == 0) {
deny_deletes = git_config_bool(var, value);
return 0;
@@ -401,6 +407,11 @@ static const char *update(struct command *cmd)
unsigned char *new_sha1 = cmd->new_sha1;
struct ref_lock *lock;
+ if (deny_all) {
+ rp_error("denying all updates");
+ return "update prohibited";
+ }
+
/* only refs/... are allowed */
if (prefixcmp(name, "refs/") || check_refname_format(name + 5, 0)) {
rp_error("refusing to create funny ref '%s' remotely", name);
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b0062ba..9d63622 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2250,6 +2250,7 @@ _git_config ()
rebase.autosquash
rebase.stat
receive.autogc
+ receive.denyAll
receive.denyCurrentBranch
receive.denyDeleteCurrent
receive.denyDeletes
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 0eace37..e8c9be2 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -222,4 +222,21 @@ test_expect_success 'deny pushing to delete current branch' '
)
'
+test_expect_success 'deny pushing to any branch with denyAll' '
+ rewound_push_setup &&
+ (
+ cd parent &&
+ git config receive.denyCurrentBranch false &&
+ git config receive.denyAll true
+ ) &&
+ (
+ cd child &&
+ test_must_fail git send-pack ../parent master 2>errs
+ ) &&
+ (
+ cd child &&
+ test_must_fail git send-pack ../parent :refs/heads/master 2>errs
+ )
+'
+
test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index b69cf57..d1117c0 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -815,6 +815,18 @@ test_expect_success 'allow push to HEAD of bare repository (bare)' '
! grep "warning: updating the current branch" stderr
'
+test_expect_success 'deny push to HEAD of bare repository (denyAll)' '
+ mk_test heads/master &&
+ (
+ cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch false &&
+ git config receive.denyAll true &&
+ git config core.bare true
+ ) &&
+ test_must_fail git push testrepo master
+'
+
test_expect_success 'allow push to HEAD of non-bare repository (config)' '
mk_test heads/master &&
(
--
1.7.8
^ permalink raw reply related
* [PATCH] fix git-gui crash due to uninitialized variable
From: Clemens Buchacher @ 2012-01-21 17:57 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Recently, a clone initiated via git gui on Windows crashed on me due to
an "unknown variable cdone". It turns out that there is a code path
where this variable is used uninitialized.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
---
Looking at the output of display(), it's not clear to me now the
function below could ever be called with total=0. But I can't delve into
it more deeply right now, and this seems like an obvious fix.
git-gui/lib/status_bar.tcl | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/git-gui/lib/status_bar.tcl b/git-gui/lib/status_bar.tcl
index 95cb449..02111a1 100644
--- a/git-gui/lib/status_bar.tcl
+++ b/git-gui/lib/status_bar.tcl
@@ -77,6 +77,7 @@ method start {msg uds} {
method update {have total} {
set pdone 0
+ set cdone 0
if {$total > 0} {
set pdone [expr {100 * $have / $total}]
set cdone [expr {[winfo width $w_c] * $have / $total}]
--
1.7.8
^ permalink raw reply related
* Including git-describe info as version strings for generic "-v" output
From: Harry portobello @ 2012-01-21 19:09 UTC (permalink / raw)
To: git; +Cc: Harry portobello
Hi all,
I hope the subject makes sense -- I'll explain what I'm trying to do.
I'm wondering what the best approaches are to being able to include
output from git-describe [1] for generic version strings in projects
managed by Git? This would have to work from within an
autotools-managed project.
At the moment, I've managed to hook the output from git-describe in to
a few .m4 files, which works only at ./configure time -- but of
course, with this being Git, I'd ideally like the same mechanism to
work in a situation where someone does:
$ git pull && make
It's knowing how to plumb this in to the Makefile.am part I'm hazy over.
Any help would be much appreciated.
Harry
[1] I know it's "git describe"; I'm using its hyphenated form for
clarity of context.
^ permalink raw reply
* [BUG] "git diff FILE BRANCH:FILE" erroneously report FILE does not exist in BRANCH
From: Stefano Lattarini @ 2012-01-21 19:36 UTC (permalink / raw)
To: git
Here is a complete reproducer for the bug:
mkdir foo \
&& cd foo \
&& git init . \
&& >README \
&& git add README \
&& git commit -m "for all" \
&& git checkout -b devel \
&& echo dev > README \
&& git add README \
&& git commit -m "for developers" \
&& git diff devel:README master:README \
&& git diff README master:README
I'd expect the last "git diff" to report the same diffs as the previous one;
instead, it errors out with this bogus message:
fatal: Path 'README' exists on disk, but not in 'master'.
Behaviour verified with git version 1.7.7.3 (installed from official Debian
packages) and the latest git development version (1.7.9.rc0.69.gbddcef, from
master).
Regards, and thanks for your amazing software,
Stefano
^ permalink raw reply
* [PATCH V4] git on Mac OS and precomposed unicode
From: Torsten Bögershausen @ 2012-01-21 19:36 UTC (permalink / raw)
To: git; +Cc: tboegi
Changes since V3:
- Be much more defensive:
Do not set core.precomposedunicode=true, even if the file system
probing indicates that it could be true.
(but we don't say that it should be true).
This is to keep better backward compatibility within git.
The user needs to manually enable the precomposition.
However, the .git/config indicates that we have a new
configuration variable, and will encourage people to use it.
- compat/precomposed_utf8.c:
- re-order #includes
- Added some empty lines to make code easier to read.
- Small fixes (xmalloc, errno handling)
- Make function names more consistent by renaming these functions:
argv_precompose() -> precompose_argv()
str_precompose() -> precompose_str()
- Improved the commit message
Torsten Bögershausen (1):
git on Mac OS and precomposed unicode
Documentation/config.txt | 9 ++
Makefile | 3 +
builtin/init-db.c | 2 +
compat/precomposed_utf8.c | 208 ++++++++++++++++++++++++++++++++++++++++++
compat/precomposed_utf8.h | 30 ++++++
git-compat-util.h | 9 ++
git.c | 1 +
t/t3910-mac-os-precompose.sh | 117 +++++++++++++++++++++++
8 files changed, 379 insertions(+), 0 deletions(-)
create mode 100644 compat/precomposed_utf8.c
create mode 100644 compat/precomposed_utf8.h
create mode 100755 t/t3910-mac-os-precompose.sh
--
1.7.8.rc0.43.gb49a8
^ permalink raw reply
* [PATCH V4] git on Mac OS and precomposed unicode
From: Torsten Bögershausen @ 2012-01-21 19:36 UTC (permalink / raw)
To: git; +Cc: tboegi
Allow git on Mac OS to store file names in the index in precomposed unicode,
while the file system uses decomposed unicode.
The problem:
When a file called "LATIN CAPITAL LETTER A WITH DIAERESIS"
(in utf-8 encoded as 0xc3 0x84) is created, the Mac OS filesystem
converts "precomposed unicode" into "decomposed unicode".
This means that readdir() will return 0x41 0xcc 0x88.
Git under Mac OS reverts the unicode decomposition of filenames.
This is useful when pulling/pushing from repositories containing utf-8
encoded filenames using precomposed utf-8 like Linux or Windows (*).
It allows sharing git repositories stored on a VFAT file system
(e.g. a USB stick), and mounted network share using samba.
* (Not all Windows versions support UTF-8 yet:
Msysgit needs the unicode branch, cygwin supports UTF-8 since 1.7)
A new confguration variable is added: "core.precomposedunicode"
If set to false, git behaves exactly as older versions of git.
When a new git version is installed and there is a repository
where the configuration "core.precomposedunicode" is not present,
the new git is backward compatible.
The code in compat/precomposed_utf8.c implements basically 4 new functions:
precomposed_utf8_opendir(), precomposed_utf8_readdir(),
precomposed_utf8_closedir() precompose_argv()
In order to prevent that ever a file name in decomposed unicode is entering
the index, a "brute force" attempt is taken:
all arguments into git (argv[1]..argv[n]) are converted into
precomposed unicode.
This is done in git.c by calling precompose_argv().
This function is actually a #define, and it is only defined under Mac OS.
Nothing is converted on any other OS.
Auto sensing:
When creating a new git repository with "git init" or "git clone",
"core.precomposedunicode" will be set "false".
The user needs to activate this feature manually.
She typically sets core.precomposedunicode to "true" on HFS and VFAT,
or file systems mounted via SAMBA onto a Linux box.
Signed-off-by: Torsten Bögershausen <tboegi@web.de>
---
Documentation/config.txt | 9 ++
Makefile | 3 +
builtin/init-db.c | 2 +
compat/precomposed_utf8.c | 208 ++++++++++++++++++++++++++++++++++++++++++
compat/precomposed_utf8.h | 30 ++++++
git-compat-util.h | 9 ++
git.c | 1 +
t/t3910-mac-os-precompose.sh | 117 +++++++++++++++++++++++
8 files changed, 379 insertions(+), 0 deletions(-)
create mode 100644 compat/precomposed_utf8.c
create mode 100644 compat/precomposed_utf8.h
create mode 100755 t/t3910-mac-os-precompose.sh
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2959390..29ba4b0 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -175,6 +175,15 @@ The default is false, except linkgit:git-clone[1] or linkgit:git-init[1]
will probe and set core.ignorecase true if appropriate when the repository
is created.
+core.precomposedunicode::
+ This option is only used by Mac OS implementation of git.
+ When core.precomposedunicode=true,
+ git reverts the unicode decomposition of filenames done by Mac OS.
+ This is useful when pulling/pushing from repositories containing utf-8
+ encoded filenames using precomposed unicode (like Linux).
+ When false, file names are handled fully transparent by git.
+ If in doubt, keep core.precomposedunicode=false.
+
core.trustctime::
If false, the ctime differences between the index and the
working tree are ignored; useful when the inode change time
diff --git a/Makefile b/Makefile
index b21d2f1..a912b45 100644
--- a/Makefile
+++ b/Makefile
@@ -519,6 +519,7 @@ LIB_H += compat/bswap.h
LIB_H += compat/cygwin.h
LIB_H += compat/mingw.h
LIB_H += compat/obstack.h
+LIB_H += compat/precomposed_utf8.h
LIB_H += compat/win32/pthread.h
LIB_H += compat/win32/syslog.h
LIB_H += compat/win32/poll.h
@@ -884,6 +885,8 @@ ifeq ($(uname_S),Darwin)
endif
NO_MEMMEM = YesPlease
USE_ST_TIMESPEC = YesPlease
+ COMPAT_OBJS += compat/precomposed_utf8.o
+ BASIC_CFLAGS += -DPRECOMPOSED_UNICODE
endif
ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 0dacb8b..06953df 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -290,6 +290,8 @@ static int create_default_files(const char *template_path)
strcpy(path + len, "CoNfIg");
if (!access(path, F_OK))
git_config_set("core.ignorecase", "true");
+
+ probe_utf8_pathname_composition(path, len);
}
return reinit;
diff --git a/compat/precomposed_utf8.c b/compat/precomposed_utf8.c
new file mode 100644
index 0000000..285fb45
--- /dev/null
+++ b/compat/precomposed_utf8.c
@@ -0,0 +1,208 @@
+#define __PRECOMPOSED_UNICODE_C__
+
+#include "../cache.h"
+#include "../utf8.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "precomposed_utf8.h"
+
+static int mac_os_precomposed_unicode;
+const static char *repo_encoding = "UTF-8";
+const static char *path_encoding = "UTF-8-MAC";
+
+
+/* Code borrowed from utf8.c */
+#if defined(OLD_ICONV) || (defined(__sun__) && !defined(_XPG6))
+ typedef const char * iconv_ibp;
+#else
+ typedef char * iconv_ibp;
+#endif
+
+static char *reencode_string_iconv(const char *in, size_t insz, iconv_t conv)
+{
+ size_t outsz, outalloc;
+ char *out, *outpos;
+ iconv_ibp cp;
+
+ outsz = insz;
+ outalloc = outsz + 1; /* for terminating NUL */
+ out = xmalloc(outalloc);
+ outpos = out;
+ cp = (iconv_ibp)in;
+
+ while (1) {
+ size_t cnt = iconv(conv, &cp, &insz, &outpos, &outsz);
+
+ if (cnt == -1) {
+ size_t sofar;
+ if (errno != E2BIG) {
+ free(out);
+ return NULL;
+ }
+ /* insz has remaining number of bytes.
+ * since we started outsz the same as insz,
+ * it is likely that insz is not enough for
+ * converting the rest.
+ */
+ sofar = outpos - out;
+ outalloc = sofar + insz * 2 + 32;
+ out = xrealloc(out, outalloc);
+ outpos = out + sofar;
+ outsz = outalloc - sofar - 1;
+ }
+ else {
+ *outpos = '\0';
+ break;
+ }
+ }
+ return out;
+}
+
+static size_t has_utf8(const char *s, size_t maxlen, size_t *strlen_c)
+{
+ const uint8_t *utf8p = (const uint8_t*) s;
+ size_t strlen_chars = 0;
+ size_t ret = 0;
+
+ if ((!utf8p) || (!*utf8p))
+ return 0;
+
+ while((*utf8p) && maxlen) {
+ if (*utf8p & 0x80)
+ ret++;
+ strlen_chars++;
+ utf8p++;
+ maxlen--;
+ }
+ if (strlen_c)
+ *strlen_c = strlen_chars;
+
+ return ret;
+}
+
+
+void probe_utf8_pathname_composition(char *path, int len)
+{
+ const static char *auml_nfc = "\xc3\xa4";
+ const static char *auml_nfd = "\x61\xcc\x88";
+ int output_fd;
+ path[len] = 0;
+ strcpy(path + len, auml_nfc);
+ output_fd = open(path, O_CREAT|O_EXCL|O_RDWR, 0600);
+ if (output_fd >=0) {
+ close(output_fd);
+ path[len] = 0;
+ strcpy(path + len, auml_nfd);
+ if (0 == access(path, R_OK))
+ git_config_set("core.precomposedunicode", "false");
+ path[len] = 0;
+ strcpy(path + len, auml_nfc);
+ unlink(path);
+ }
+}
+
+
+static int precomposed_unicode_config(const char *var, const char *value, void *cb)
+{
+ if (!strcasecmp(var, "core.precomposedunicode")) {
+ mac_os_precomposed_unicode = git_config_bool(var, value);
+ return 0;
+ }
+ return 1;
+}
+
+void precompose_argv(int argc, const char **argv)
+{
+ int i = 0;
+ const char *oldarg;
+ char *newarg;
+ iconv_t ic_precompose;
+
+ git_config(precomposed_unicode_config, NULL);
+ if (!mac_os_precomposed_unicode)
+ return;
+
+ ic_precompose = iconv_open(repo_encoding, path_encoding);
+ if (ic_precompose == (iconv_t) -1)
+ return;
+
+ while (i < argc) {
+ size_t namelen;
+ oldarg = argv[i];
+ if (has_utf8(oldarg, (size_t)-1, &namelen)) {
+ newarg = reencode_string_iconv(oldarg, namelen, ic_precompose);
+ if (newarg)
+ argv[i] = newarg;
+ }
+ i++;
+ }
+ iconv_close(ic_precompose);
+}
+
+
+PRECOMPOSED_UTF_DIR * precomposed_utf8_opendir(const char *dirname)
+{
+ PRECOMPOSED_UTF_DIR *precomposed_utf8_dir;
+ precomposed_utf8_dir = xmalloc(sizeof(PRECOMPOSED_UTF_DIR));
+
+ precomposed_utf8_dir->dirp = opendir(dirname);
+ if (!precomposed_utf8_dir->dirp) {
+ free(precomposed_utf8_dir);
+ return NULL;
+ }
+ precomposed_utf8_dir->ic_precompose = iconv_open(repo_encoding, path_encoding);
+ if (precomposed_utf8_dir->ic_precompose == (iconv_t) -1) {
+ closedir(precomposed_utf8_dir->dirp);
+ free(precomposed_utf8_dir);
+ return NULL;
+ }
+
+ return precomposed_utf8_dir;
+}
+
+struct dirent * precomposed_utf8_readdir(PRECOMPOSED_UTF_DIR *precomposed_utf8_dirp)
+{
+ struct dirent *res;
+ size_t namelen = 0;
+
+ res = readdir(precomposed_utf8_dirp->dirp);
+ if (res && mac_os_precomposed_unicode && has_utf8(res->d_name, (size_t)-1, &namelen)) {
+ int ret_errno = errno;
+ size_t outsz = sizeof(precomposed_utf8_dirp->dirent_nfc.d_name) - 1; /* one for \0 */
+ char *outpos = precomposed_utf8_dirp->dirent_nfc.d_name;
+ iconv_ibp cp;
+ size_t cnt;
+ size_t insz = namelen;
+ cp = (iconv_ibp)res->d_name;
+
+ /* Copy all data except the name */
+ memcpy(&precomposed_utf8_dirp->dirent_nfc, res,
+ sizeof(precomposed_utf8_dirp->dirent_nfc)-sizeof(precomposed_utf8_dirp->dirent_nfc.d_name));
+ errno = 0;
+
+ cnt = iconv(precomposed_utf8_dirp->ic_precompose, &cp, &insz, &outpos, &outsz);
+ if (cnt < sizeof(precomposed_utf8_dirp->dirent_nfc.d_name) -1) {
+ *outpos = 0;
+ errno = ret_errno;
+ return &precomposed_utf8_dirp->dirent_nfc;
+ }
+ errno = ret_errno;
+ }
+ return res;
+}
+
+
+int precomposed_utf8_closedir(PRECOMPOSED_UTF_DIR *precomposed_utf8_dirp)
+{
+ int ret_value;
+ int ret_errno;
+ ret_value = closedir(precomposed_utf8_dirp->dirp);
+ ret_errno = errno;
+ if (precomposed_utf8_dirp->ic_precompose != (iconv_t)-1)
+ iconv_close(precomposed_utf8_dirp->ic_precompose);
+ free(precomposed_utf8_dirp);
+ errno = ret_errno;
+ return ret_value;
+}
diff --git a/compat/precomposed_utf8.h b/compat/precomposed_utf8.h
new file mode 100644
index 0000000..79e65e7
--- /dev/null
+++ b/compat/precomposed_utf8.h
@@ -0,0 +1,30 @@
+#ifndef __PRECOMPOSED_UNICODE_H__
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <iconv.h>
+
+
+typedef struct {
+ iconv_t ic_precompose;
+ DIR *dirp;
+ struct dirent dirent_nfc;
+} PRECOMPOSED_UTF_DIR;
+
+char *precompose_str(const char *in, iconv_t ic_precompose);
+void precompose_argv(int argc, const char **argv);
+void probe_utf8_pathname_composition(char *, int);
+
+PRECOMPOSED_UTF_DIR *precomposed_utf8_opendir(const char *dirname);
+struct dirent *precomposed_utf8_readdir(PRECOMPOSED_UTF_DIR *dirp);
+int precomposed_utf8_closedir(PRECOMPOSED_UTF_DIR *dirp);
+
+#ifndef __PRECOMPOSED_UNICODE_C__
+#define opendir(n) precomposed_utf8_opendir(n)
+#define readdir(d) precomposed_utf8_readdir(d)
+#define closedir(d) precomposed_utf8_closedir(d)
+#define DIR PRECOMPOSED_UTF_DIR
+#endif /* __PRECOMPOSED_UNICODE_C__ */
+
+#define __PRECOMPOSED_UNICODE_H__
+#endif /* __PRECOMPOSED_UNICODE_H__ */
diff --git a/git-compat-util.h b/git-compat-util.h
index 230e198..8911743 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -153,6 +153,15 @@
#include "compat/msvc.h"
#endif
+/* used on Mac OS X */
+#ifdef PRECOMPOSED_UNICODE
+#include "compat/precomposed_utf8.h"
+#else
+#define precompose_str(in,i_nfd2nfc)
+#define precompose_argv(c,v)
+#define probe_utf8_pathname_composition(a,b)
+#endif
+
#ifndef NO_LIBGEN_H
#include <libgen.h>
#else
diff --git a/git.c b/git.c
index 8e34903..265db96 100644
--- a/git.c
+++ b/git.c
@@ -298,6 +298,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */
trace_repo_setup(prefix);
}
+ precompose_argv(argc, argv);
commit_pager_choice();
if (!help && p->option & NEED_WORK_TREE)
diff --git a/t/t3910-mac-os-precompose.sh b/t/t3910-mac-os-precompose.sh
new file mode 100755
index 0000000..ba3d83c
--- /dev/null
+++ b/t/t3910-mac-os-precompose.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Torsten Bögershausen
+#
+
+test_description='utf-8 decomposed (nfd) converted to precomposed (nfc)'
+
+. ./test-lib.sh
+
+Adiarnfc=`printf '\303\204'`
+Odiarnfc=`printf '\303\226'`
+Adiarnfd=`printf 'A\314\210'`
+Odiarnfd=`printf 'O\314\210'`
+
+mkdir junk &&
+>junk/"$Adiarnfc" &&
+case "$(cd junk && echo *)" in
+ "$Adiarnfd")
+ test_nfd=1
+ ;;
+ *) ;;
+esac
+rm -rf junk
+
+if test "$test_nfd"
+then
+ test_expect_success "detect if nfd needed" '
+ precomposedunicode=`git config core.precomposedunicode` &&
+ test "$precomposedunicode" = false &&
+ git config core.precomposedunicode true
+ '
+ test_expect_success "setup" '
+ >x &&
+ git add x &&
+ git commit -m "1st commit" &&
+ git rm x &&
+ git commit -m "rm x"
+ '
+ test_expect_success "setup case mac" '
+ git checkout -b mac_os
+ '
+ # This will test nfd2nfc in readdir()
+ test_expect_success "add file Adiarnfc" '
+ echo f.Adiarnfc >f.$Adiarnfc &&
+ git add f.$Adiarnfc &&
+ git commit -m "add f.$Adiarnfc"
+ '
+ # This will test nfd2nfc in git stage()
+ test_expect_success "stage file d.Adiarnfd/f.Adiarnfd" '
+ mkdir d.$Adiarnfd &&
+ echo d.$Adiarnfd/f.$Adiarnfd >d.$Adiarnfd/f.$Adiarnfd &&
+ git stage d.$Adiarnfd/f.$Adiarnfd &&
+ git commit -m "add d.$Adiarnfd/f.$Adiarnfd"
+ '
+ test_expect_success "add link Adiarnfc" '
+ ln -s d.$Adiarnfd/f.$Adiarnfd l.$Adiarnfc &&
+ git add l.$Adiarnfc &&
+ git commit -m "add l.Adiarnfc"
+ '
+ # This will test git log
+ test_expect_success "git log f.Adiar" '
+ git log f.$Adiarnfc > f.Adiarnfc.log &&
+ git log f.$Adiarnfd > f.Adiarnfd.log &&
+ test -s f.Adiarnfc.log &&
+ test -s f.Adiarnfd.log &&
+ test_cmp f.Adiarnfc.log f.Adiarnfd.log &&
+ rm f.Adiarnfc.log f.Adiarnfd.log
+ '
+ # This will test git ls-files
+ test_expect_success "git lsfiles f.Adiar" '
+ git ls-files f.$Adiarnfc > f.Adiarnfc.log &&
+ git ls-files f.$Adiarnfd > f.Adiarnfd.log &&
+ test -s f.Adiarnfc.log &&
+ test -s f.Adiarnfd.log &&
+ test_cmp f.Adiarnfc.log f.Adiarnfd.log &&
+ rm f.Adiarnfc.log f.Adiarnfd.log
+ '
+ # This will test git mv
+ test_expect_success "git mv" '
+ git mv f.$Adiarnfd f.$Odiarnfc &&
+ git mv d.$Adiarnfd d.$Odiarnfc &&
+ git mv l.$Adiarnfd l.$Odiarnfc &&
+ git commit -m "mv Adiarnfd Odiarnfc"
+ '
+ # Files can be checked out as nfc
+ # And the link has been corrected from nfd to nfc
+ test_expect_success "git checkout nfc" '
+ rm f.$Odiarnfc &&
+ git checkout f.$Odiarnfc
+ '
+ # Make it possible to checkout files with their NFD names
+ test_expect_success "git checkout file nfd" '
+ rm -f f.* &&
+ git checkout f.$Odiarnfd
+ '
+ # Make it possible to checkout links with their NFD names
+ test_expect_success "git checkout link nfd" '
+ rm l.* &&
+ git checkout l.$Odiarnfd
+ '
+ test_expect_success "setup case mac2" '
+ git checkout master &&
+ git reset --hard &&
+ git checkout -b mac_os_2
+ '
+ # This will test nfd2nfc in git commit
+ test_expect_success "commit file d2.Adiarnfd/f.Adiarnfd" '
+ mkdir d2.$Adiarnfd &&
+ echo d2.$Adiarnfd/f.$Adiarnfd >d2.$Adiarnfd/f.$Adiarnfd &&
+ git add d2.$Adiarnfd/f.$Adiarnfd &&
+ git commit -m "add d2.$Adiarnfd/f.$Adiarnfd" -- d2.$Adiarnfd/f.$Adiarnfd
+ '
+else
+ say "Skipping nfc/nfd tests"
+fi
+
+test_done
--
1.7.8.rc0.43.gb49a8
^ permalink raw reply related
* Re: [PATCH] mergetool: Suppress stderr and fix the "both added" test
From: Junio C Hamano @ 2012-01-21 21:27 UTC (permalink / raw)
To: David Aguilar; +Cc: jcwenger, git
In-Reply-To: <1327141578-54796-1-git-send-email-davvid@gmail.com>
David Aguilar <davvid@gmail.com> writes:
> Silence error messages when "git checkout-index" is used to
> checkout a stage that does not exist. This can happen now that
> mergetool calls checkout_staged_file() unconditionally when
> creating the temporary $BASE, $LOCAL, and $REMOTE files.
>
> Fix the test so that it checks the contents of the "both added"
> file. The test was passing as a consequence of accidentally
> handing a bad path to "cat".
>
> Signed-off-by: David Aguilar <davvid@gmail.com>
> ---
> This applies on top of da/maint-mergetool-twoway in pu.
Thanks.
It might make sense to squash this into the previous patch, which luckily
hasn't hit 'next' yet, though---which I can do locally without need for
re-send if you like.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox