Git development
 help / color / mirror / Atom feed
* Cannot push a commit
From: Matthias Fechner @ 2012-01-15  9:09 UTC (permalink / raw)
  To: git

Dear List,

I have a big problem with a file which I cannot push to my central git
repository.
The file can be found here:
http://dl.fechner.net/APP_UD.sch

What I did to reproduce it:
On my server (freebsd with git 1.7.8.3)
cd
mkdir git-test
cd git-test
git init --bare

On my client a windows pc with tortoise git 1.7.6.0 and git 1.7.8.msysgit.0
I cloned the repository over ssh
Added a small test.txt file, commit and pushed it to the server,
everything is fine.
Then a copied the file above to the local repo, added it and commited it.
If I try to push it, I get the error message:
git.exe push --progress  "origin" master:master

Counting objects: 4, done.
Compressing objects: 100% (3/3)
Writing objects: 100% (3/3), 80.00 KiB | 137 KiB/s
Writing objects: 100% (3/3), 91.63 KiB | 137 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
fatal: early EOF
error: unpack failed: unpack-objects abnormal exit
To idefix@fechner.net:git-test
! [remote rejected] master -> master (n/a (unpacker error))
error: failed to push some refs to 'idefix@fechner.net:git-test'

git config -l shows on the windows pc:
core.symlinks=false
core.autocrlf=false
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
pack.packsizelimit=2g
help.format=html
http.sslcainfo=/bin/curl-ca-bundle.crt
sendemail.smtpserver=/bin/msmtp.exe
diff.astextplain.textconv=astextplain
rebase.autosquash=true
user.name=Matthias Fechner
user.email=idefix@fechner.net
core.autocrlf=false
core.safecrlf=false
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
core.hidedotfiles=dotGitOnly
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=idefix@fechner.net:git-test
remote.origin.puttykeyfile=
branch.master.remote=origin
branch.master.merge=refs/heads/master

How can I solve this problem?
Is this maybe a bug in git?

Thanks a lot
Matthias

-- 

"Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the universe trying to
produce bigger and better idiots. So far, the universe is winning." --
Rich Cook

^ permalink raw reply

* Re: git grep doesn't follow symbolic link
From: Nguyen Thai Ngoc Duy @ 2012-01-15  9:47 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Pang Yan Han, Thomas Rast, Ramkumar Ramachandra, Bertrand BENOIT,
	git
In-Reply-To: <7v1ur1yazf.fsf@alter.siamese.dyndns.org>

On Sun, Jan 15, 2012 at 9:07 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Stop and think what "git diff --follow-symlinks v1.3.0 v1.7.0" should do
> when these versions record a symbolic link, "from user perspective", if
> the link points outside the tracked contents. Naturally, the users would
> expect that the comparison is made between the contents of the file back
> when v1.3.0 was tagged and the contents of the file (which may or may not
> be the same path depending on the target of that symbolic link) back when
> v1.7.0 was tagged.
>
> But that is something that the user is *NOT* tracking with the system, and
> hence something we cannot give the right answer. Your "--follow-symlinks"
> option only encourages the *wrong* perception on the users' side, without
> supporting what it appears to promise to the users. Why could it be an
> improvement?

It's not wrong per se. It's an implication that users have to take
when they choose to use it. We may help make it clear that the
symlinks point to untracked files by putting some indication in the
diff.

When I do "git log -Sfoo -- '*.cxx'" I don't really care if bar.cxx is
a symlink. Neither does my compiler. It may be a symlink's target
change that makes "foo" appear. Git could help me detect that quickly
instead of sticking with tracked contents only.

Even if we decide --follow-symlinks=untracked is a bad idea,
--follow-symlinks=tracked (i.e. follow symlinks to tracked files only)
is still a good thing to support. And I suspect that's a more common
case as linking outside repository could is undeterministic.

The "=tracked" could be dropped if we have no other option value. I'm
thinking of --follow-symlinks=submodule, which is currently covered by
a separate option name.
-- 
Duy

^ permalink raw reply

* Re: [PATCH v2 1/2] Document limited recursion pathspec matching with wildcards
From: Nguyen Thai Ngoc Duy @ 2012-01-15  9:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jonathan Nieder, Linus Torvalds
In-Reply-To: <7vfwfhwuzd.fsf@alter.siamese.dyndns.org>

2012/1/15 Junio C Hamano <gitster@pobox.com>:
>> @@ -79,6 +79,9 @@ OPTIONS
>>  --max-depth <depth>::
>>       For each <pathspec> given on command line, descend at most <depth>
>>       levels of directories. A negative value means no limit.
>> +     This option is ignored if <pathspec> contains active wildcards.
>> +     In other words if "a*" matches a directory named "a*",
>> +     "*" is matched literally so --max-depth is still effective.
>
> Do we have a definition of "active wildcard"?

Probably not. I did not know how to phrase it and ended up with
"active wildcard" and an example for clarification.
-- 
Duy

^ permalink raw reply

* Re: [PATCH v2 2/2] tree_entry_interesting: make recursive mode default
From: Nguyen Thai Ngoc Duy @ 2012-01-15 10:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jonathan Nieder, Linus Torvalds
In-Reply-To: <7v8vl9wtfg.fsf@alter.siamese.dyndns.org>

On Sat, Jan 14, 2012 at 07:12:03PM -0800, Junio C Hamano wrote:
> That makes my head hurt and makes me suspect there is something
> fundamentally wrong in the patch.  Sigh...

I'll need to think about it. In the meantime perhaps the following
bandage patch would suffice, rather than revert 2f88c19 (diff-index:
pass pathspec down to unpack-trees machinery)

-- 8< --
Subject: [PATCH] diff-index: enable recursive pathspec matching in unpack_trees

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 diff-lib.c               |    2 ++
 t/t4010-diff-pathspec.sh |    8 ++++++++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/diff-lib.c b/diff-lib.c
index 62f4cd9..fc0dff3 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -469,6 +469,8 @@ static int diff_cache(struct rev_info *revs,
 	opts.src_index = &the_index;
 	opts.dst_index = NULL;
 	opts.pathspec = &revs->diffopt.pathspec;
+	opts.pathspec->recursive = 1;
+	opts.pathspec->max_depth = -1;
 
 	init_tree_desc(&t, tree->buffer, tree->size);
 	return unpack_trees(1, &t, &opts);
diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh
index fbc8cd8..af5134b 100755
--- a/t/t4010-diff-pathspec.sh
+++ b/t/t4010-diff-pathspec.sh
@@ -48,6 +48,14 @@ test_expect_success \
      compare_diff_raw current expected'
 
 cat >expected <<\EOF
+:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M	path1/file1
+EOF
+test_expect_success \
+    '"*file1" should show path1/file1' \
+    'git diff-index --cached $tree -- "*file1" >current &&
+     compare_diff_raw current expected'
+
+cat >expected <<\EOF
 :100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M	file0
 EOF
 test_expect_success \
-- 
1.7.8.36.g69ee2

-- 8< --
-- 
Duy

^ permalink raw reply related

* Re: Bug! Git merge also fails with a wrong error message
From: Jakub Narebski @ 2012-01-15 10:08 UTC (permalink / raw)
  To: Yves Goergen; +Cc: Carlos Martín Nieto, git
In-Reply-To: <4F128B81.2000502@unclassified.de>

On Sun, 15 Jan 2012, Yves Goergen wrote:
> On 13.01.2012 20:34 CE(S)T, Jakub Narebski wrote:

> > > Since I don't have access to the news system, I need to use the Gmane
> > > website. I don't know exactly what it is.
> > 
> > GMane is an e-mail to news gateway, and a mailing list archive. It
> > exposes mailing list as a newsgroup, so it can be read and written to
> > via newsreader (via Usenet).
> 
> I have Thunderbird, but I have no usenet server to entry in a usenet
> account, so as I said, I don't have access to that part of the internet.
> I had at university, but that's some time ago now.

GMane serves as a Usenet server; that is how it works as mail to news
gateway.  The server name is news.gmane.org... or you can try using the
following URL

  nntp://news.gmane.org/gmane.comp.version-control.git
 
> > git@vger.kernel.org is a public non-subscribe mailing list; you don't
> > need to subscribe to post requests there.  Note that it is a custom on
> > this mailing list to always include all participants in given
> > (sub)thread directly in Cc, so you should get responses to your emails
> > even if you are not subscribed.
> 
> Good to know NOW. It really should have informed me in the first place
> on that website. It's a vital information without which you likely won't
> get anywhere (as I).

You can get this information on GitCommunity page on Git Wiki.  For the
time being (while Git Wiki is served as set of static pages of exported
contents because of lack of hardware) you can find it here:

  https://git.wiki.kernel.org/articles/g/i/t/GitCommunity_c4e3.html

-- 
Jakub Narebski
Poland

^ permalink raw reply

* [PATCH] test-lib: add the test_bash convenience function
From: Jens Lehmann @ 2012-01-15 20:00 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Jeff King, Junio C Hamano

Since 781f76b15 (test-lib: redirect stdin of tests) you can't simply put a
"bash &&" into a test for debugging purposes anymore. Instead you'll have
to use "bash <&6 >&3 2>&4".

As that invocation is not that easy to remember add the test_bash
convenience function. This function also checks if the -v flag is given
and will complain if that is not the case instead of letting the test
hang until ^D is pressed.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
---

I was tempted to call that method "run_bash" but after looking around
in test-lib.sh "test_bash" seemed like a better name.

 t/test-lib.sh |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index a65dfc7..f9061e0 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -329,6 +329,17 @@ test_tick () {
 	export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
 }

+# Stop execution and start a bash shell. This is useful for debugging tests
+# and only makes sense together with "-v".
+
+test_bash () {
+	if test "$verbose" = t; then
+		bash <&6 >&3 2>&4
+	else
+		say >&5 "skipping test_bash as it makes no sense without -v"
+	fi
+}
+
 # Call test_commit with the arguments "<message> [<file> [<contents>]]"
 #
 # This will commit a file with the given contents and the given commit
-- 
1.7.9.rc1.1.g46aa0.dirty

^ permalink raw reply related

* Re: [PATCH] test-lib: add the test_bash convenience function
From: Jeff King @ 2012-01-15 23:24 UTC (permalink / raw)
  To: Jens Lehmann; +Cc: Git Mailing List, Junio C Hamano
In-Reply-To: <4F133069.10308@web.de>

On Sun, Jan 15, 2012 at 09:00:41PM +0100, Jens Lehmann wrote:

> Since 781f76b15 (test-lib: redirect stdin of tests) you can't simply put a
> "bash &&" into a test for debugging purposes anymore. Instead you'll have
> to use "bash <&6 >&3 2>&4".

Yeah, an unfortunate side effect.

If you're not relying on particular state in the middle of a chain of
commands, you can just put the "bash" outside of the test_expect_*. But
sometimes you do care about having it in the middle.

> As that invocation is not that easy to remember add the test_bash
> convenience function. This function also checks if the -v flag is given
> and will complain if that is not the case instead of letting the test
> hang until ^D is pressed.

Nice. Many times I have added such a "bash" or "gdb" invocation then
forgotten "-v", only to scratch my head at why the test seemed to be
hanging.

Two minor nits on the patch itself:

> +# Stop execution and start a bash shell. This is useful for debugging tests
> +# and only makes sense together with "-v".
> +
> +test_bash () {
> +	if test "$verbose" = t; then
> +		bash <&6 >&3 2>&4
> +	else
> +		say >&5 "skipping test_bash as it makes no sense without -v"
> +	fi
> +}

1. It may be worth putting a warning in the comment that this is never
   to be used in a real test, but only temporarily inserted.

2. I do this not just with bash, but with "gdb". I wonder if it is worth
   making this "test_foo bash", for some value of "foo" (the ones that
   occur to me are "debug" and "run", but of course they are taken).

   Actually, I wonder if the existing test_debug could handle this
   already (though you do have to remember to add "--debug" to your
   command line, then).

-Peff

^ permalink raw reply

* Re: Re* Regulator updates for 3.3
From: Pete Harlan @ 2012-01-16  0:14 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Linus Torvalds, Mark Brown, Liam Girdwood, linux-kernel,
	Git Mailing List
In-Reply-To: <7vzkdu7miv.fsf@alter.siamese.dyndns.org>

On 01/10/2012 10:59 PM, Junio C Hamano wrote:
> There may be existing scripts that leave the standard input and the
> standard output of the "git merge" connected to whatever environment the
> scripts were started, and such invocation might trigger the above
> "interactive session" heuristics. Such scripts can export GIT_MERGE_LEGACY
> environment variable set to "yes" to force the traditional behaviour.

The name GIT_MERGE_LEGACY gives no clue about what flavor of legacy
merge behavior is being enabled.  Something like GIT_MERGE_LEGACY_EDIT
might be clearer, or perhaps just have GIT_MERGE_EDIT=0 to get the old
behavior without reference to whether or not that behavior is
considered legacy.

--Pete

^ permalink raw reply

* [PATCH 0/3] git-p4: Search for parent commit on branch creation
From: Vitor Antunes @ 2012-01-16  0:39 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Vitor Antunes

This patch was originally sent as a RFC and was improved since then
according to feedback given by Pete Wyckoff. At the time it required
calling fast-import with the --force argument. To avoid this the new
version tracks the temporary branches created during post-processing and
removes them at the end of the import process.

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 |   39 ++++++++++++++++++++-
 t/t9801-git-p4-branch.sh   |   83 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+), 1 deletions(-)

-- 
1.7.8.3

^ permalink raw reply

* [PATCH 1/3] git-p4: Add checkpoint() task
From: Vitor Antunes @ 2012-01-16  0:39 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Vitor Antunes
In-Reply-To: <1326674360-2771-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.8.3

^ permalink raw reply related

* [PATCH 2/3] git-p4: Search for parent commit on branch creation
From: Vitor Antunes @ 2012-01-16  0:39 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Vitor Antunes
In-Reply-To: <1326674360-2771-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 |   31 ++++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 417d119..e2f9165 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,28 @@ class P4Sync(Command, P4UserMap):
                             parent = self.initialParents[branch]
                             del self.initialParents[branch]
 
-                        self.commit(description, filesForCommit, branch, [branchPrefix], parent)
+                        parentFound = 0
+                        if len(parent) > 0:
+                            self.checkpoint()
+                            for blob in read_pipe_lines("git rev-list --reverse --no-merges %s" % parent):
+                                blob = blob.strip()
+                                tempBranch = self.tempBranchLocation + os.sep + "%d-%s" % (change, blob)
+                                if self.verbose:
+                                    print "Creating temporary branch: " + tempBranch
+                                self.commit(description, filesForCommit, tempBranch, [branchPrefix], blob)
+                                self.tempBranches.append(tempBranch)
+                                self.checkpoint()
+                                if len( read_pipe("git diff-tree %s %s" % (blob, tempBranch)) ) == 0:
+                                    parentFound = 1
+                                    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 +2370,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:
+                os.remove(".git" + os.sep + branch)
+            os.rmdir(".git" + os.sep + self.tempBranchLocation)
+
         return True
 
 class P4Rebase(Command):
-- 
1.7.8.3

^ permalink raw reply related

* [PATCH 3/3] git-p4: Add test case for complex branch import
From: Vitor Antunes @ 2012-01-16  0:39 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Vitor Antunes
In-Reply-To: <1326674360-2771-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 |   83 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index a25f18d..0f10e00 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -226,6 +226,89 @@ 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" &&
+		cd "$TRASH_DIRECTORY"
+	)
+'
+
+# 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" &&
+	(
+		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 -f file1 &&
+		test -f file2 &&
+		test -f file3 &&
+		grep -q update file2 &&
+		git reset --hard p4/depot/branch2 &&
+		test -f file1 &&
+		test -f file2 &&
+		test ! -f file3 &&
+		! grep -q update file2 &&
+		git reset --hard p4/depot/branch3 &&
+		test -f file1 &&
+		test -f file2 &&
+		test -f file3 &&
+		grep -q update file2 &&
+		git reset --hard p4/depot/branch4 &&
+		test -f file1 &&
+		test -f file2 &&
+		test ! -f file3 &&
+		! grep -q update file2 &&
+		git reset --hard p4/depot/branch5 &&
+		test -f file1 &&
+		test -f file2 &&
+		test -f file3 &&
+		! grep -q update file2 &&
+		test ! -d .git/git-p4-tmp
+	)
+'
+
 test_expect_success 'kill p4d' '
 	kill_p4d
 '
-- 
1.7.8.3

^ permalink raw reply related

* Unexpected "clean -Xd" behavior
From: Pete Harlan @ 2012-01-16  2:00 UTC (permalink / raw)
  To: Git Mailing List

Hi,

When a directory contains nothing but an ignored subdirectory, that
subdirectory does not get removed by "git clean -Xdf".

For example, in a new directory:

# git init
Initialized empty Git repository in /tmp/foo/.git/
# echo a/ >.gitignore
# git add .gitignore
# git commit -m "Initial commit"
[master (root-commit) c3af24c] Initial commit
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore
# mkdir -p foo/a
# touch foo/a/junk.o
# git status
# On branch master
nothing to commit (working directory clean)
# git clean -Xdn  # <--- DOES NOT MENTION foo/a
# touch foo/x.c
# git clean -Xdn  # <--- DITTO WITH UNTRACKED IN foo
# git add foo/x.c
# git clean -Xdn  # <--- WITH TRACKED IN foo, WILL REMOVE a/
Would remove foo/a/
#

Is this intentional?  It's interfering with my using "git clean" to
remove built objects, which happen to be in a dedicated temporary
subdirectory.

Thanks,

--Pete Harlan
  pgit@pcharlan.com

^ permalink raw reply

* [PATCH 0/2] nd/commit-ignore-i-t-a replacement
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  2:36 UTC (permalink / raw)
  To: git; +Cc: Jonathan Nieder, Junio C Hamano,
	Nguyễn Thái Ngọc Duy

This replaces current topic branch in pu with a more sensible
approach using config key. write-tree also learns about this.

Nguyễn Thái Ngọc Duy (2):
  cache-tree: update API to take abitrary flags
  commit, write-tree: allow to ignore CE_INTENT_TO_ADD while writing
    trees

 Documentation/config.txt         |    5 +++++
 Documentation/git-add.txt        |   12 ++++++++++--
 Documentation/git-write-tree.txt |    8 +++++++-
 builtin/commit.c                 |   13 ++++++++++---
 builtin/write-tree.c             |    2 ++
 cache-tree.c                     |   35 +++++++++++++++++------------------
 cache-tree.h                     |    5 ++++-
 merge-recursive.c                |    2 +-
 t/t2203-add-intent.sh            |   30 ++++++++++++++++++++++++++++++
 test-dump-cache-tree.c           |    2 +-
 10 files changed, 87 insertions(+), 27 deletions(-)

-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply

* [PATCH 2/2] commit, write-tree: allow to ignore CE_INTENT_TO_ADD while writing trees
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  2:36 UTC (permalink / raw)
  To: git; +Cc: Jonathan Nieder, Junio C Hamano,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1326681407-6344-1-git-send-email-pclouds@gmail.com>

Normally cache-tree will not produce trees from an index that has
CE_INTENT_TO_ADD entries. This is a safe measure to avoid
mis-interpreting user's intention regarding this flag.

There are situations however where users want to create trees/commits
regardless i-t-a entries. Allow such cases with commit.ignoreIntentToAdd
for git-commit and --ignore-intent-to-add for git-write-tree.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/config.txt         |    5 +++++
 Documentation/git-add.txt        |   12 ++++++++++--
 Documentation/git-write-tree.txt |    8 +++++++-
 builtin/commit.c                 |   13 ++++++++++---
 builtin/write-tree.c             |    2 ++
 cache-tree.c                     |    8 +++++---
 cache-tree.h                     |    1 +
 t/t2203-add-intent.sh            |   30 ++++++++++++++++++++++++++++++
 8 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index abeb82b..10c3767 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -831,6 +831,11 @@ commit.template::
 	"{tilde}/" is expanded to the value of `$HOME` and "{tilde}user/" to the
 	specified user's home directory.
 
+commit.ignoreIntentToAdd::
+	Allow to commit the index as-is even if there are
+	intent-to-add entries (see option `-N` in linkgit:git-add[1])
+	in index.
+
 credential.helper::
 	Specify an external helper to be called when a username or
 	password credential is needed; the helper may consult external
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 9c1d395..ec548ea 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -123,8 +123,16 @@ subdirectories.
 	Record only the fact that the path will be added later. An entry
 	for the path is placed in the index with no content. This is
 	useful for, among other things, showing the unstaged content of
-	such files with `git diff` and committing them with `git commit
-	-a`.
+	such files with `git diff`.
++
+Paths added with this option have intent-to-add flag in index. The
+flag is removed once real content is added or updated. By default you
+cannot commit the index as-is from until this flag is removed from all
+entries (i.e. all entries have real content). See commit.ignoreIntentToAdd
+regardless the flag.
++
+Committing with `git commit -a` or with selected paths works
+regardless the config key and the flag.
 
 --refresh::
 	Don't add the file(s), but only refresh their stat()
diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt
index f22041a..d511d3a 100644
--- a/Documentation/git-write-tree.txt
+++ b/Documentation/git-write-tree.txt
@@ -9,7 +9,7 @@ git-write-tree - Create a tree object from the current index
 SYNOPSIS
 --------
 [verse]
-'git write-tree' [--missing-ok] [--prefix=<prefix>/]
+'git write-tree' [--missing-ok] [--ignore-intent-to-add] [--prefix=<prefix>/]
 
 DESCRIPTION
 -----------
@@ -32,6 +32,12 @@ OPTIONS
 	directory exist in the object database.  This option disables this
 	check.
 
+--ignore-intent-to-add::
+	Normally 'git write-tree' will refuse to proceed if there are any
+	intent-to-add entries (see `-N` option in linkgit:git-add[1]).
+	This option continues to create object tree as if there are no
+	intent-to-add entries in index.
+
 --prefix=<prefix>/::
 	Writes a tree object that represents a subdirectory
 	`<prefix>`.  This can be used to write the tree object
diff --git a/builtin/commit.c b/builtin/commit.c
index bf42bb3..097699e 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -86,6 +86,7 @@ static int all, also, interactive, patch_interactive, only, amend, signoff;
 static int edit_flag = -1; /* unspecified */
 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
 static int no_post_rewrite, allow_empty_message;
+static int cache_tree_flags;
 static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
 static char *sign_commit;
 
@@ -400,7 +401,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
 		fd = hold_locked_index(&index_lock, 1);
 		add_files_to_cache(also ? prefix : NULL, pathspec, 0);
 		refresh_cache_or_die(refresh_flags);
-		update_main_cache_tree(WRITE_TREE_SILENT);
+		update_main_cache_tree(cache_tree_flags | WRITE_TREE_SILENT);
 		if (write_cache(fd, active_cache, active_nr) ||
 		    close_lock_file(&index_lock))
 			die(_("unable to write new_index file"));
@@ -421,7 +422,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
 		fd = hold_locked_index(&index_lock, 1);
 		refresh_cache_or_die(refresh_flags);
 		if (active_cache_changed) {
-			update_main_cache_tree(WRITE_TREE_SILENT);
+			update_main_cache_tree(cache_tree_flags | WRITE_TREE_SILENT);
 			if (write_cache(fd, active_cache, active_nr) ||
 			    commit_locked_index(&index_lock))
 				die(_("unable to write new_index file"));
@@ -870,7 +871,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 	 */
 	discard_cache();
 	read_cache_from(index_file);
-	if (update_main_cache_tree(0)) {
+	if (update_main_cache_tree(cache_tree_flags)) {
 		error(_("Error building trees"));
 		return 0;
 	}
@@ -1338,6 +1339,12 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		include_status = git_config_bool(k, v);
 		return 0;
 	}
+	if (!strcmp(k, "commit.ignoreintenttoadd")) {
+		if (git_config_bool(k, v))
+			cache_tree_flags |= WRITE_TREE_IGNORE_INTENT_TO_ADD;
+		else
+			cache_tree_flags &= ~WRITE_TREE_IGNORE_INTENT_TO_ADD;
+	}
 
 	status = git_gpg_config(k, v, NULL);
 	if (status)
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index b223af4..07797bb 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -23,6 +23,8 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
 	struct option write_tree_options[] = {
 		OPT_BIT(0, "missing-ok", &flags, "allow missing objects",
 			WRITE_TREE_MISSING_OK),
+		OPT_BIT(0, "ignore-intent-to-add", &flags, "ignore i-t-a entries in index",
+			WRITE_TREE_IGNORE_INTENT_TO_ADD ),
 		{ OPTION_STRING, 0, "prefix", &prefix, "<prefix>/",
 		  "write tree object for a subdirectory <prefix>" ,
 		  PARSE_OPT_LITERAL_ARGHELP },
diff --git a/cache-tree.c b/cache-tree.c
index 16355d6..d0be159 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -159,7 +159,9 @@ static int verify_cache(struct cache_entry **cache,
 	funny = 0;
 	for (i = 0; i < entries; i++) {
 		struct cache_entry *ce = cache[i];
-		if (ce_stage(ce) || (ce->ce_flags & CE_INTENT_TO_ADD)) {
+		if (ce_stage(ce) ||
+		    ((flags & WRITE_TREE_IGNORE_INTENT_TO_ADD) == 0 &&
+		     (ce->ce_flags & CE_INTENT_TO_ADD))) {
 			if (silent)
 				return -1;
 			if (10 < ++funny) {
@@ -339,8 +341,8 @@ static int update_one(struct cache_tree *it,
 				mode, sha1_to_hex(sha1), entlen+baselen, path);
 		}
 
-		if (ce->ce_flags & CE_REMOVE)
-			continue; /* entry being removed */
+		if (ce->ce_flags & (CE_REMOVE | CE_INTENT_TO_ADD))
+			continue; /* entry being removed or placeholder */
 
 		strbuf_grow(&buffer, entlen + 100);
 		strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
diff --git a/cache-tree.h b/cache-tree.h
index d8cb2e9..af3b917 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -38,6 +38,7 @@ int update_main_cache_tree(int);
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
 #define WRITE_TREE_DRY_RUN 4
 #define WRITE_TREE_SILENT 8
+#define WRITE_TREE_IGNORE_INTENT_TO_ADD 16
 
 /* error return codes */
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index 58a3299..7b447d3 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -44,6 +44,36 @@ test_expect_success 'cannot commit with i-t-a entry' '
 	test_must_fail git commit
 '
 
+test_expect_success 'can write-tree with i-t-a entry' '
+	git reset --hard &&
+	echo xyzzy >rezrov &&
+	echo frotz >nitfol &&
+	git add rezrov &&
+	git add -N nitfol &&
+	git write-tree --ignore-intent-to-add >actual &&
+	echo 150389afa1ccf46e4104667c741cd0e598269511 >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'can commit tree with i-t-a entry' '
+	git reset --hard &&
+	echo xyzzy >rezrov &&
+	echo frotz >nitfol &&
+	git add rezrov &&
+	git add -N nitfol &&
+	git config commit.ignoreIntentToAdd true &&
+	git commit -m initial &&
+	git ls-tree -r HEAD >actual &&
+	cat >expected <<EOF &&
+100644 blob ce013625030ba8dba906f756967f9e9ca394464a	elif
+100644 blob ce013625030ba8dba906f756967f9e9ca394464a	file
+100644 blob cf7711b63209d0dbc2d030f7fe3513745a9880e4	rezrov
+EOF
+	test_cmp expected actual &&
+	git config commit.ignoreIntentToAdd false &&
+	git reset HEAD^
+'
+
 test_expect_success 'can commit with an unrelated i-t-a entry in index' '
 	git reset --hard &&
 	echo xyzzy >rezrov &&
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 1/2] cache-tree: update API to take abitrary flags
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  2:36 UTC (permalink / raw)
  To: git; +Cc: Jonathan Nieder, Junio C Hamano,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1326681407-6344-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/commit.c       |    4 ++--
 cache-tree.c           |   27 ++++++++++++---------------
 cache-tree.h           |    4 +++-
 merge-recursive.c      |    2 +-
 test-dump-cache-tree.c |    2 +-
 5 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index eba1377..bf42bb3 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -400,7 +400,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
 		fd = hold_locked_index(&index_lock, 1);
 		add_files_to_cache(also ? prefix : NULL, pathspec, 0);
 		refresh_cache_or_die(refresh_flags);
-		update_main_cache_tree(1);
+		update_main_cache_tree(WRITE_TREE_SILENT);
 		if (write_cache(fd, active_cache, active_nr) ||
 		    close_lock_file(&index_lock))
 			die(_("unable to write new_index file"));
@@ -421,7 +421,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
 		fd = hold_locked_index(&index_lock, 1);
 		refresh_cache_or_die(refresh_flags);
 		if (active_cache_changed) {
-			update_main_cache_tree(1);
+			update_main_cache_tree(WRITE_TREE_SILENT);
 			if (write_cache(fd, active_cache, active_nr) ||
 			    commit_locked_index(&index_lock))
 				die(_("unable to write new_index file"));
diff --git a/cache-tree.c b/cache-tree.c
index 8de3959..16355d6 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -150,9 +150,10 @@ void cache_tree_invalidate_path(struct cache_tree *it, const char *path)
 }
 
 static int verify_cache(struct cache_entry **cache,
-			int entries, int silent)
+			int entries, int flags)
 {
 	int i, funny;
+	int silent = flags & WRITE_TREE_SILENT;
 
 	/* Verify that the tree is merged */
 	funny = 0;
@@ -241,10 +242,11 @@ static int update_one(struct cache_tree *it,
 		      int entries,
 		      const char *base,
 		      int baselen,
-		      int missing_ok,
-		      int dryrun)
+		      int flags)
 {
 	struct strbuf buffer;
+	int missing_ok = flags & WRITE_TREE_MISSING_OK;
+	int dryrun = flags & WRITE_TREE_DRY_RUN;
 	int i;
 
 	if (0 <= it->entry_count && has_sha1_file(it->sha1))
@@ -288,8 +290,7 @@ static int update_one(struct cache_tree *it,
 				    cache + i, entries - i,
 				    path,
 				    baselen + sublen + 1,
-				    missing_ok,
-				    dryrun);
+				    flags);
 		if (subcnt < 0)
 			return subcnt;
 		i += subcnt - 1;
@@ -371,15 +372,13 @@ static int update_one(struct cache_tree *it,
 int cache_tree_update(struct cache_tree *it,
 		      struct cache_entry **cache,
 		      int entries,
-		      int missing_ok,
-		      int dryrun,
-		      int silent)
+		      int flags)
 {
 	int i;
-	i = verify_cache(cache, entries, silent);
+	i = verify_cache(cache, entries, flags);
 	if (i)
 		return i;
-	i = update_one(it, cache, entries, "", 0, missing_ok, dryrun);
+	i = update_one(it, cache, entries, "", 0, flags);
 	if (i < 0)
 		return i;
 	return 0;
@@ -572,11 +571,9 @@ int write_cache_as_tree(unsigned char *sha1, int flags, const char *prefix)
 
 	was_valid = cache_tree_fully_valid(active_cache_tree);
 	if (!was_valid) {
-		int missing_ok = flags & WRITE_TREE_MISSING_OK;
-
 		if (cache_tree_update(active_cache_tree,
 				      active_cache, active_nr,
-				      missing_ok, 0, 0) < 0)
+				      flags) < 0)
 			return WRITE_TREE_UNMERGED_INDEX;
 		if (0 <= newfd) {
 			if (!write_cache(newfd, active_cache, active_nr) &&
@@ -672,10 +669,10 @@ int cache_tree_matches_traversal(struct cache_tree *root,
 	return 0;
 }
 
-int update_main_cache_tree (int silent)
+int update_main_cache_tree (int flags)
 {
 	if (!the_index.cache_tree)
 		the_index.cache_tree = cache_tree();
 	return cache_tree_update(the_index.cache_tree,
-				 the_index.cache, the_index.cache_nr, 0, 0, silent);
+				 the_index.cache, the_index.cache_nr, flags);
 }
diff --git a/cache-tree.h b/cache-tree.h
index 0ec0b2a..d8cb2e9 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -29,13 +29,15 @@ void cache_tree_write(struct strbuf *, struct cache_tree *root);
 struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
 
 int cache_tree_fully_valid(struct cache_tree *);
-int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int, int);
+int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int);
 
 int update_main_cache_tree(int);
 
 /* bitmasks to write_cache_as_tree flags */
 #define WRITE_TREE_MISSING_OK 1
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
+#define WRITE_TREE_DRY_RUN 4
+#define WRITE_TREE_SILENT 8
 
 /* error return codes */
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
diff --git a/merge-recursive.c b/merge-recursive.c
index d83cd6c..6479a60 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -264,7 +264,7 @@ struct tree *write_tree_from_memory(struct merge_options *o)
 
 	if (!cache_tree_fully_valid(active_cache_tree) &&
 	    cache_tree_update(active_cache_tree,
-			      active_cache, active_nr, 0, 0, 0) < 0)
+			      active_cache, active_nr, 0) < 0)
 		die("error building trees");
 
 	result = lookup_tree(active_cache_tree->sha1);
diff --git a/test-dump-cache-tree.c b/test-dump-cache-tree.c
index e6c2923..a6ffdf3 100644
--- a/test-dump-cache-tree.c
+++ b/test-dump-cache-tree.c
@@ -59,6 +59,6 @@ int main(int ac, char **av)
 	struct cache_tree *another = cache_tree();
 	if (read_cache() < 0)
 		die("unable to read index file");
-	cache_tree_update(another, active_cache, active_nr, 0, 1, 0);
+	cache_tree_update(another, active_cache, active_nr, WRITE_TREE_DRY_RUN);
 	return dump_cache_tree(active_cache_tree, another, "");
 }
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 0/5] Dynamic diff summary for merge/pull
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  4:47 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Linus Torvalds,
	Nguyễn Thái Ngọc Duy

On Sat, Jan 14, 2012 at 2:49 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> And what I've *really* wanted is to actually see the diff itself if
> it
> is small. So some kind of "dynamic summary": for one-liners (or
> ten-liners), show the whole diff. For medium-sized changes, show the
> whole diffstat. And for really big changes, show an outline and the
> "768 files changed, 179851 lines added, 7630 lines removed" stats.
>
> IOW, whatever fits in, say, 50 lines or less.

Here's an attempt to do that. The main patch is 4/5 to implement
--dynstat. 5/5 just makes merge/pull pass --dynstat to diff machinery.

--dynstat tries various diff output and use one that fits within 50
lines:

 --patch + --shortstat
 --stat (maybe plus --summary)
 --dirstat + --shortstat
 --shortstat

Many hardcoded constants should be more flexible (i.e. 50 lines limit
could be retrieved from terminal settigns), but that's minor for
now imo. I think we should also hint users to do
"git diff --stat --summary HEAD@{1} HEAD" too via advice framework if
we turn --dynstat to default for merge/pull

I have not run "make test" so it may break a few tests because of 2/2.

Nguyễn Thái Ngọc Duy (5):
  diff: add space around "="
  diff: do not duplicate shortstat with "git diff --stat --shortstat"
  diff: buffer dirstat output
  diff: add --dynstat
  merge: support setting merge.[diff]stat to dynstat

 builtin/merge.c |   30 +++++++++++--
 diff.c          |  127 +++++++++++++++++++++++++++++++++++++++++++++++--------
 diff.h          |    1 +
 3 files changed, 135 insertions(+), 23 deletions(-)

-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply

* [PATCH 1/5] diff: add space around "="
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  4:47 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Linus Torvalds,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1326689281-23788-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 diff.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/diff.c b/diff.c
index 374ecf3..d4223e2 100644
--- a/diff.c
+++ b/diff.c
@@ -1482,7 +1482,7 @@ static void show_shortstats(struct diffstat_t *data, struct diff_options *option
 		if (!data->files[i]->is_binary &&
 		    !data->files[i]->is_unmerged) {
 			int added = data->files[i]->added;
-			int deleted= data->files[i]->deleted;
+			int deleted = data->files[i]->deleted;
 			if (!data->files[i]->is_renamed &&
 			    (added + deleted == 0)) {
 				total_files--;
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 2/5] diff: do not duplicate shortstat with "git diff --stat --shortstat"
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  4:47 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Linus Torvalds,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1326689281-23788-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 diff.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/diff.c b/diff.c
index d4223e2..203b054 100644
--- a/diff.c
+++ b/diff.c
@@ -1465,10 +1465,6 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 			fprintf(options->file, "%s ...\n", line_prefix);
 		extra_shown = 1;
 	}
-	fprintf(options->file, "%s", line_prefix);
-	fprintf(options->file,
-	       " %d files changed, %d insertions(+), %d deletions(-)\n",
-	       total_files, adds, dels);
 }
 
 static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
@@ -4218,6 +4214,9 @@ void diff_flush(struct diff_options *options)
 	if (output_format & DIFF_FORMAT_DIRSTAT && DIFF_OPT_TST(options, DIRSTAT_BY_LINE))
 		dirstat_by_line = 1;
 
+	if (output_format & DIFF_FORMAT_DIFFSTAT)
+		output_format |= DIFF_FORMAT_SHORTSTAT;
+
 	if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT) ||
 	    dirstat_by_line) {
 		struct diffstat_t diffstat;
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 3/5] diff: buffer dirstat output
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  4:47 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Linus Torvalds,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1326689281-23788-1-git-send-email-pclouds@gmail.com>

This allows us to decide whether to print it later on.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 diff.c |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/diff.c b/diff.c
index 203b054..8c448b5 100644
--- a/diff.c
+++ b/diff.c
@@ -1548,6 +1548,7 @@ struct dirstat_file {
 struct dirstat_dir {
 	struct dirstat_file *files;
 	int alloc, nr, permille, cumulative;
+	struct strbuf *sb;
 };
 
 static long gather_dirstat(struct diff_options *opt, struct dirstat_dir *dir,
@@ -1597,8 +1598,8 @@ static long gather_dirstat(struct diff_options *opt, struct dirstat_dir *dir,
 		if (this_dir) {
 			int permille = this_dir * 1000 / changed;
 			if (permille >= dir->permille) {
-				fprintf(opt->file, "%s%4d.%01d%% %.*s\n", line_prefix,
-					permille / 10, permille % 10, baselen, base);
+				strbuf_addf(dir->sb, "%s%4d.%01d%% %.*s\n", line_prefix,
+					    permille / 10, permille % 10, baselen, base);
 				if (!dir->cumulative)
 					return 0;
 			}
@@ -1614,18 +1615,20 @@ static int dirstat_compare(const void *_a, const void *_b)
 	return strcmp(a->name, b->name);
 }
 
-static void show_dirstat(struct diff_options *options)
+static void show_dirstat(struct diff_options *options, struct strbuf *output)
 {
 	int i;
 	unsigned long changed;
 	struct dirstat_dir dir;
 	struct diff_queue_struct *q = &diff_queued_diff;
+	struct strbuf sb = STRBUF_INIT;
 
 	dir.files = NULL;
 	dir.alloc = 0;
 	dir.nr = 0;
 	dir.permille = options->dirstat_permille;
 	dir.cumulative = DIFF_OPT_TST(options, DIRSTAT_CUMULATIVE);
+	dir.sb = output ? output : &sb;
 
 	changed = 0;
 	for (i = 0; i < q->nr; i++) {
@@ -1711,6 +1714,9 @@ found_damage:
 	/* Show all directories with more than x% of the changes */
 	qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare);
 	gather_dirstat(options, &dir, changed, "", 0);
+	if (!output)
+		fputs(sb.buf, options->file);
+	strbuf_release(&sb);
 }
 
 static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *options)
@@ -1718,6 +1724,7 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
 	int i;
 	unsigned long changed;
 	struct dirstat_dir dir;
+	struct strbuf sb = STRBUF_INIT;
 
 	if (data->nr == 0)
 		return;
@@ -1727,6 +1734,7 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
 	dir.nr = 0;
 	dir.permille = options->dirstat_permille;
 	dir.cumulative = DIFF_OPT_TST(options, DIRSTAT_CUMULATIVE);
+	dir.sb = &sb;
 
 	changed = 0;
 	for (i = 0; i < data->nr; i++) {
@@ -1755,6 +1763,8 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
 	/* Show all directories with more than x% of the changes */
 	qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare);
 	gather_dirstat(options, &dir, changed, "", 0);
+	fputs(sb.buf, options->file);
+	strbuf_release(&sb);
 }
 
 static void free_diffstat_info(struct diffstat_t *diffstat)
@@ -4239,7 +4249,7 @@ void diff_flush(struct diff_options *options)
 		separator++;
 	}
 	if ((output_format & DIFF_FORMAT_DIRSTAT) && !dirstat_by_line)
-		show_dirstat(options);
+		show_dirstat(options, NULL);
 
 	if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) {
 		for (i = 0; i < q->nr; i++) {
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 4/5] diff: add --dynstat
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  4:48 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Linus Torvalds,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1326689281-23788-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 diff.c |  100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 diff.h |    1 +
 2 files changed, 92 insertions(+), 9 deletions(-)

diff --git a/diff.c b/diff.c
index 8c448b5..b945ad6 100644
--- a/diff.c
+++ b/diff.c
@@ -1226,6 +1226,7 @@ struct diffstat_t {
 		unsigned is_renamed:1;
 		uintmax_t added, deleted;
 	} **files;
+	struct strbuf dynstat;
 };
 
 static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
@@ -1779,6 +1780,7 @@ static void free_diffstat_info(struct diffstat_t *diffstat)
 		free(f);
 	}
 	free(diffstat->files);
+	strbuf_release(&diffstat->dynstat);
 }
 
 struct checkdiff_t {
@@ -3332,6 +3334,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		options->output_format |= DIFF_FORMAT_NUMSTAT;
 	else if (!strcmp(arg, "--shortstat"))
 		options->output_format |= DIFF_FORMAT_SHORTSTAT;
+	else if (!strcmp(arg, "--dynstat"))
+		options->output_format |= DIFF_FORMAT_DYNSTAT;
 	else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat"))
 		return parse_dirstat_opt(options, "");
 	else if (!prefixcmp(arg, "-X"))
@@ -3922,6 +3926,76 @@ static int check_pair_status(struct diff_filepair *p)
 	}
 }
 
+static int diff_flush_dynstat(struct diff_options *o, struct diffstat_t *diffstat)
+{
+	struct diff_queue_struct *q = &diff_queued_diff;
+	int i, adds = 0, dels = 0, summary_lines = 0, printed_lines = 0, total_files;
+
+	memset(diffstat, 0, sizeof(struct diffstat_t));
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		if (check_pair_status(p))
+			diff_flush_stat(p, o, diffstat);
+	}
+
+	total_files = diffstat->nr;
+	if (!total_files)
+		return o->output_format;
+
+	/* how many lines for --stat ? */
+	for (i = 0; i < diffstat->nr; i++) {
+		struct diffstat_file *f = diffstat->files[i];
+		if (!f->is_binary && !f->is_unmerged) {
+			if (!f->is_renamed && (f->added + f->deleted == 0))
+				total_files--;
+			else {
+				adds += f->added;
+				dels += f->deleted;
+			}
+		}
+	}
+
+	/* how many lines for --summary ? */
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		if ((p->status & (DIFF_STATUS_DELETED | DIFF_STATUS_ADDED |
+				 DIFF_STATUS_COPIED | DIFF_STATUS_RENAMED)) ||
+		    p->score)
+			summary_lines++;
+	}
+
+	if (printed_lines + total_files < 50) {
+		o->output_format |= DIFF_FORMAT_DIFFSTAT;
+		printed_lines += total_files;
+		if (printed_lines + summary_lines < 50) {
+			printed_lines += summary_lines;
+			o->output_format |= DIFF_FORMAT_SUMMARY;
+		}
+	} else {
+		const char *s;
+		int nr = 0;
+		show_dirstat(o, &diffstat->dynstat);
+		s = diffstat->dynstat.buf;
+
+		/* how many lines for --dirstat ? */
+		while (s && (s = strchr(s, '\n'))) {
+			nr++;
+			s++;
+		}
+		if (nr < 50)
+			printed_lines += nr;
+		else
+			strbuf_release(&diffstat->dynstat);
+	}
+
+	/* how many lines for --patch ? */
+	if (adds + dels < 10 && printed_lines < 10)
+		o->output_format |= DIFF_FORMAT_PATCH;
+
+	o->output_format |= DIFF_FORMAT_SHORTSTAT;
+	return o->output_format;
+}
+
 static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
 {
 	int fmt = opt->output_format;
@@ -4201,6 +4275,7 @@ void diff_flush(struct diff_options *options)
 	int i, output_format = options->output_format;
 	int separator = 0;
 	int dirstat_by_line = 0;
+	struct diffstat_t diffstat;
 
 	/*
 	 * Order: raw, stat, summary, patch
@@ -4221,6 +4296,19 @@ void diff_flush(struct diff_options *options)
 		separator++;
 	}
 
+	memset(&diffstat, 0, sizeof(struct diffstat_t));
+	strbuf_init(&diffstat.dynstat, 0);
+	if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DYNSTAT)) {
+		for (i = 0; i < q->nr; i++) {
+			struct diff_filepair *p = q->queue[i];
+			if (check_pair_status(p))
+				diff_flush_stat(p, options, &diffstat);
+		}
+	}
+
+	if (output_format & DIFF_FORMAT_DYNSTAT)
+		output_format = diff_flush_dynstat(options, &diffstat);
+
 	if (output_format & DIFF_FORMAT_DIRSTAT && DIFF_OPT_TST(options, DIRSTAT_BY_LINE))
 		dirstat_by_line = 1;
 
@@ -4229,25 +4317,19 @@ void diff_flush(struct diff_options *options)
 
 	if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT) ||
 	    dirstat_by_line) {
-		struct diffstat_t diffstat;
-
-		memset(&diffstat, 0, sizeof(struct diffstat_t));
-		for (i = 0; i < q->nr; i++) {
-			struct diff_filepair *p = q->queue[i];
-			if (check_pair_status(p))
-				diff_flush_stat(p, options, &diffstat);
-		}
 		if (output_format & DIFF_FORMAT_NUMSTAT)
 			show_numstat(&diffstat, options);
 		if (output_format & DIFF_FORMAT_DIFFSTAT)
 			show_stats(&diffstat, options);
+		if ((output_format & DIFF_FORMAT_DYNSTAT) && diffstat.dynstat.len)
+			fputs(diffstat.dynstat.buf, options->file);
 		if (output_format & DIFF_FORMAT_SHORTSTAT)
 			show_shortstats(&diffstat, options);
 		if (output_format & DIFF_FORMAT_DIRSTAT)
 			show_dirstat_by_line(&diffstat, options);
-		free_diffstat_info(&diffstat);
 		separator++;
 	}
+	free_diffstat_info(&diffstat);
 	if ((output_format & DIFF_FORMAT_DIRSTAT) && !dirstat_by_line)
 		show_dirstat(options, NULL);
 
diff --git a/diff.h b/diff.h
index ae71f4c..6bebad8 100644
--- a/diff.h
+++ b/diff.h
@@ -39,6 +39,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
 #define DIFF_FORMAT_PATCH	0x0010
 #define DIFF_FORMAT_SHORTSTAT	0x0020
 #define DIFF_FORMAT_DIRSTAT	0x0040
+#define DIFF_FORMAT_DYNSTAT	0x0080
 
 /* These override all above */
 #define DIFF_FORMAT_NAME	0x0100
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH 5/5] merge: support setting merge.[diff]stat to dynstat
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  4:48 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Linus Torvalds,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1326689281-23788-1-git-send-email-pclouds@gmail.com>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/merge.c |   30 +++++++++++++++++++++++++-----
 1 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 3a45172..b8280ce 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -46,7 +46,13 @@ static const char * const builtin_merge_usage[] = {
 	NULL
 };
 
-static int show_diffstat = 1, shortlog_len = -1, squash;
+enum show_diffstat {
+	NO_STAT,
+	DIFF_STAT,
+	DYNAMIC_STAT
+};
+
+static int show_diffstat = NO_STAT, shortlog_len = -1, squash;
 static int option_commit = 1, allow_fast_forward = 1;
 static int fast_forward_only, option_edit;
 static int allow_trivial = 1, have_message;
@@ -399,8 +405,15 @@ static void finish(struct commit *head_commit,
 	if (new_head && show_diffstat) {
 		struct diff_options opts;
 		diff_setup(&opts);
-		opts.output_format |=
-			DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
+		switch (show_diffstat) {
+		case DIFF_STAT:
+			opts.output_format |=
+				DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
+			break;
+		case DYNAMIC_STAT:
+			opts.output_format |= DIFF_FORMAT_DYNSTAT;
+			break;
+		}
 		opts.detect_rename = DIFF_DETECT_RENAME;
 		if (diff_setup_done(&opts) < 0)
 			die(_("diff_setup_done failed"));
@@ -554,8 +567,15 @@ static int git_merge_config(const char *k, const char *v, void *cb)
 		return 0;
 	}
 
-	if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
-		show_diffstat = git_config_bool(k, v);
+	if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat")) {
+		int val = git_config_maybe_bool(k, v);
+		if (val != -1)
+			show_diffstat = val ? DIFF_STAT : NO_STAT;
+		else if (!strcasecmp(v, "dynstat"))
+			show_diffstat = DYNAMIC_STAT;
+		else
+			die(_("unrecognized value \"%s\" for %s"), v, k);
+	}
 	else if (!strcmp(k, "pull.twohead"))
 		return git_config_string(&pull_twohead, k, v);
 	else if (!strcmp(k, "pull.octopus"))
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH v5 00/10] nd/clone-detached rebase onto nd/clone-single-branch
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  9:46 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1326439322-15648-1-git-send-email-pclouds@gmail.com>

There are a few more changes than just a simple rebase so that
"git clone --depth=1 --branch=tag" also works.

Nguyễn Thái Ngọc Duy (10):
  t5601: add missing && cascade
  clone: write detached HEAD in bare repositories
  clone: factor out checkout code
  clone: factor out HEAD update code
  clone: factor out remote ref writing
  clone: delay cloning until after remote HEAD checking
  clone: --branch=<branch> always means refs/heads/<branch>
  clone: refuse to clone if --branch points to bogus ref
  clone: allow --branch to take a tag
  clone: print advice on checking out detached HEAD

 Documentation/git-clone.txt |    5 +-
 advice.c                    |   14 ++
 advice.h                    |    1 +
 builtin/checkout.c          |   16 +--
 builtin/clone.c             |  297 +++++++++++++++++++++++++------------------
 t/t5500-fetch-pack.sh       |   22 ++-
 t/t5601-clone.sh            |   40 +++++-
 t/t5706-clone-branch.sh     |    8 +-
 transport.c                 |    5 +-
 9 files changed, 249 insertions(+), 159 deletions(-)

-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply

* [PATCH v5 01/10] t5601: add missing && cascade
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  9:46 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1326439322-15648-1-git-send-email-pclouds@gmail.com>

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 t/t5601-clone.sh |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 87ee016..49821eb 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -9,9 +9,9 @@ test_expect_success setup '
 	rm -fr .git &&
 	test_create_repo src &&
 	(
-		cd src
-		>file
-		git add file
+		cd src &&
+		>file &&
+		git add file &&
 		git commit -m initial
 	)
 
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related

* [PATCH v5 02/10] clone: write detached HEAD in bare repositories
From: Nguyễn Thái Ngọc Duy @ 2012-01-16  9:46 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy
In-Reply-To: <1326439322-15648-1-git-send-email-pclouds@gmail.com>

If we don't write, HEAD is still at refs/heads/master as initialized
by init-db, which may or may not match remote's HEAD.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/clone.c  |    9 +++------
 t/t5601-clone.sh |   25 ++++++++++++++++++++++++-
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 9dcc5fe..91862f7 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -764,12 +764,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		}
 	} else if (remote_head) {
 		/* Source had detached HEAD pointing somewhere. */
-		if (!option_bare) {
-			update_ref(reflog_msg.buf, "HEAD",
-				   remote_head->old_sha1,
-				   NULL, REF_NODEREF, DIE_ON_ERR);
-			our_head_points_at = remote_head;
-		}
+		update_ref(reflog_msg.buf, "HEAD", remote_head->old_sha1,
+			   NULL, REF_NODEREF, DIE_ON_ERR);
+		our_head_points_at = remote_head;
 	} else {
 		/* Nothing to checkout out */
 		if (!option_no_checkout)
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 49821eb..e0b8db6 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -12,7 +12,10 @@ test_expect_success setup '
 		cd src &&
 		>file &&
 		git add file &&
-		git commit -m initial
+		git commit -m initial &&
+		echo 1 >file &&
+		git add file &&
+		git commit -m updated
 	)
 
 '
@@ -88,6 +91,26 @@ test_expect_success 'clone --mirror' '
 
 '
 
+test_expect_success 'clone --mirror with detached HEAD' '
+
+	( cd src && git checkout HEAD^ && git rev-parse HEAD >../expected ) &&
+	git clone --mirror src mirror.detached &&
+	( cd src && git checkout - ) &&
+	GIT_DIR=mirror.detached git rev-parse HEAD >actual &&
+	test_cmp expected actual
+
+'
+
+test_expect_success 'clone --bare with detached HEAD' '
+
+	( cd src && git checkout HEAD^ && git rev-parse HEAD >../expected ) &&
+	git clone --bare src bare.detached &&
+	( cd src && git checkout - ) &&
+	GIT_DIR=bare.detached git rev-parse HEAD >actual &&
+	test_cmp expected actual
+
+'
+
 test_expect_success 'clone --bare names the local repository <name>.git' '
 
 	git clone --bare src &&
-- 
1.7.3.1.256.g2539c.dirty

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox