Re: [PATCH 2/2] dir: remove PATH_MAX limitation

2014-07-05 Thread Duy Nguyen
On Sat, Jul 5, 2014 at 5:42 AM, Karsten Blees karsten.bl...@gmail.com wrote:
 'git status' segfaults if a directory is longer than PATH_MAX, because
 processing .gitignore files in prep_exclude() writes past the end of a
 PATH_MAX-bounded buffer.

 Remove the limitation by using strbuf instead.

 Note: this fix just 'abuses' strbuf as string allocator, len is always 0.
 prep_exclude() can probably be simplified using more strbuf APIs.

FYI I had a similar patch [1] that attempted to lazily strbuf_init()
instead so that strbuf_ API could be used.

[1] http://article.gmane.org/gmane.comp.version-control.git/248310
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: t5150-request-pull.sh fails on newest master in Debian

2014-07-05 Thread Øyvind A . Holm
On 5 July 2014 03:58, David Turner dtur...@twopensource.com wrote:
 On Sat, 2014-07-05 at 02:09 +0200, Øyvind A. Holm wrote:
 snip
  The test works. Seems as there's something fishy about the use of
  --prefix in this specific commit (v2.0.1-472-g6f92e5f).

 Ok, now I can reproduce on my linode box (haven't tried it locally
 yet). I'll try to get a fix up once I figure out what's up.

Awesome. I've done some more ./configure --prefix testing, and this is
the result:

  # --prefix is set to non-existing directory
  ./configure --prefix=/usr/local/varprg/git.master.v2.0.1-472-g6f92e5f
# ./t5150-request-pull.sh fails.

  # --prefix is set to non-existing directory, use trailing slash
  ./configure --prefix=/usr/local/varprg/git.master.v2.0.1-472-g6f92e5f/
# ./t5150-request-pull.sh fails.

  # --prefix is set to existing directory
  ./configure --prefix=/usr/local/varprg/git.master.v2.0.1-442-g7fe6834
# ./t5150-request-pull.sh fails.

  # --prefix is set to existing directory
  ./configure --prefix=/usr/local
# ./t5150-request-pull.sh succeeds.

  # --prefix is set to existing directory
  ./configure --prefix=/usr/local/varprg
# ./t5150-request-pull.sh succeeds.

  # --prefix is set to non-existing directory
  ./configure 
--prefix=/usr/local/varprg/a-long-directory-name-which-does-not-exist
# ./t5150-request-pull.sh succeeds.

  ./configure 
--prefix=/usr/local/varprg/git.master.a-long-directory-name-which-does-not-exist
# ./t5150-request-pull.sh succeeds.

So it's something with names like git.master.v2.0.1-472-g6f92e5f that
./configure --prefix is picky about.

When testing this last night, I pushed the following branches to
https://github.com/sunny256/git where I added all compiled files in
various stages with git add -f .:

  t5150-fail.configure-without-prefix
Succeeds.
./configure

  t5150-fail.configure-with-prefix
Fails.
./configure --prefix=/usr/local/varprg/git.master.v2.0.1-472-g6f92e5f

  t5150-fail.configure-prefix-usr-local
Succeeds.
./configure --prefix=/usr/local

Maybe something will turn up by diffing those branches. I've got to
leave for now, but will have a look at this later tonight.

Cheers,
Øyvind
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git fetch sha1

2014-07-05 Thread Shawn Pearce
On Sat, Jul 5, 2014 at 6:05 AM, Allan Gardner allanegard...@gmail.com wrote:
 On Fri, Jul 4, 2014 at 10:41 PM, Shawn Pearce spea...@spearce.org wrote:

 On Fri, Jul 4, 2014 at 10:51 AM, Allan Gardner allanegard...@gmail.com 
 wrote:
  Currently fetching a sha1 fails on git.kernel.org:
 
  $ git --version  uname -a
  git version 1.9.4
  Linux nixos 3.12.23 #1-NixOS SMP Thu Jan 1 00:00:01 UTC 1970 x86_64 
  GNU/Linux
 
  $ rm -rf test  mkdir test  cd test  git init
  Initialized empty Git repository in ~/test/.git/
 
  $ git fetch --depth 1 https://git.kernel.org/pub/scm/git/git.git
  782735203c316041df120748e5e88c1787cdf4da
  error: no such remote ref 782735203c316041df120748e5e88c1787cdf4da
 
  I tried with head, same error. However, if I clone the full repository
  and then manually execute git upload-pack, it successfully fetches the
  commit:
 
  $ git fetch https://git.kernel.org/pub/scm/git/git.git master
  wait an hour
  $ git checkout -b sha1 782735203c316041df120748e5e88c1787cdf4da
  $ printf 0045want %s multi_ack_detailed\n000Ddeepen
  1\n0009done\n 782735203c316041df120748e5e88c1787cdf4da
 input
  $ cat input | git upload-pack --stateless-rpc .  output
  $ sed -z s/.*0008NAK\n//  output  output.pack
  $ git index-pack output.pack  git verify-pack -v output.pack | grep 
  commit
  f239687a5dbbd1bbb761d09edec582418c66c297
  782735203c316041df120748e5e88c1787cdf4da commit 374 234 12
 
  So theoretically this is supported server-side. Unfortunately
  kernel.org does not agree:

 No, it is not supported server side. Your test didn't even test what
 you think it tested.

 $ curl 
 https://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack
 2/dev/null | head -n 2
 001e# service=git-upload-pack
 009b6f92e5ff3cdc813de8ef5327fd4bad492fb7d6c9 HEADmulti_ack
 thin-pack side-band side-band-64k ofs-delta shallow no-progress
 include-tag multi_ack_detailed

 The capability you are asking about is allow-tip-sha1-in-want which
 does not appear in the server advertisement. So its not supported on
 this server.

 $ git upload-pack --advertise-refs --stateless-rpc .
 00d16f92e5ff3cdc813de8ef5327fd4bad492fb7d6c9 HEADmulti_ack thin-pack
 side-band side-band-64k ofs-delta shallow no-progress include-tag
 multi_ack_detailed no-done symref=HEAD:refs/heads/master
 agent=git/1.9.4

 I did not ask about allow-tip-sha1-in-want,

I think you did. You asked about passing a random SHA-1 to `git
fetch`. The client will only send this SHA-1 to the server if an
advertised ref exactly matches or the server advertised
allow-tip-sha1-in-want. Otherwise, it errors out.

 and it is not enabled by
 default. It appears that the server must advertise no-done though,
 which indeed git.kernel.org does not.

no-done is unrelated to passing a SHA-1 on the fetch line. The two
concepts have nothing to do with each other. I seriously doubt anyone
piggybacked additional features onto no-done years after it was
introduced.

 So my next question is how
 git.kernel.org can set up the smart HTTP protocol without using
 --stateless-rpc; I guess I will have to ask them.

Haha!

Good luck with that. Current implementation requires --stateless-rpc
to run smart HTTP.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] refs.c: handle REFNAME_REFSPEC_PATTERN at end of page

2014-07-05 Thread David Turner
When a ref crosses a memory page boundary, we restart the parsing
at the beginning with the bytewise code.  Pass the original flags
to that code, rather than the current flags.

Signed-off-by: David Turner dtur...@twitter.com
---
 refs.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index 20e2bf1..82e4842 100644
--- a/refs.c
+++ b/refs.c
@@ -153,6 +153,7 @@ int check_refname_format(const char *refname, int flags)
const __m128i tilde_lb = _mm_set1_epi8('~' - 1);
 
int component_count = 0;
+   int orig_flags = flags;
 
if (refname[0] == 0 || refname[0] == '/') {
/* entirely empty ref or initial ref component */
@@ -178,7 +179,7 @@ int check_refname_format(const char *refname, int flags)
 * End-of-page; fall back to slow method for
 * this entire ref.
 */
-   return check_refname_format_bytewise(refname, flags);
+   return check_refname_format_bytewise(refname, 
orig_flags);
 
tmp = _mm_loadu_si128((__m128i *)cp);
tmp1 = _mm_loadu_si128((__m128i *)(cp + 1));
-- 
2.0.0.390.gcb682f8

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] t5000, t5003: simplify commit

2014-07-05 Thread René Scharfe
Add the whole directory of test files at once using git add instead of
calling git update-index on each of them and use git commit instead of
the plumbing commands write-tree, update-ref and commit-tree to build
the commit.  This simplifies the code considerably.

Signed-off-by: Rene Scharfe l@web.de
---
 t/t5000-tar-tree.sh| 12 
 t/t5003-archive-zip.sh | 12 
 2 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 899c1c5..7b8babd 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -119,14 +119,10 @@ test_expect_success \
 'echo ignore me a/ignored 
  echo ignored export-ignore .git/info/attributes'
 
-test_expect_success \
-'add files to repository' \
-'find a -type f | xargs git update-index --add 
- find a -type l | xargs git update-index --add 
- treeid=$(git write-tree) 
- echo $treeid treeid 
- git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE=2005-05-27 22:00:00 \
- git commit-tree $treeid /dev/null)'
+test_expect_success 'add files to repository' '
+   git add a 
+   GIT_COMMITTER_DATE=2005-05-27 22:00 git commit -m initial
+'
 
 test_expect_success 'setup export-subst' '
echo substfile? export-subst .git/info/attributes 
diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh
index 21a5c93..c929db5 100755
--- a/t/t5003-archive-zip.sh
+++ b/t/t5003-archive-zip.sh
@@ -61,14 +61,10 @@ test_expect_success \
 'echo ignore me a/ignored 
  echo ignored export-ignore .git/info/attributes'
 
-test_expect_success \
-'add files to repository' \
-'find a -type f | xargs git update-index --add 
- find a -type l | xargs git update-index --add 
- treeid=`git write-tree` 
- echo $treeid treeid 
- git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE=2005-05-27 22:00:00 \
- git commit-tree $treeid /dev/null)'
+test_expect_success 'add files to repository' '
+   git add a 
+   GIT_COMMITTER_DATE=2005-05-27 22:00 git commit -m initial
+'
 
 test_expect_success 'setup export-subst' '
echo substfile? export-subst .git/info/attributes 
-- 
2.0.0

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[BUG] Push fails with dumb http to SabreDAV

2014-07-05 Thread Abbaad Haider
Background:
I'm trying to host a git repository at my Box.com account, which
offers DAV access using a server called SabreDAV. I ran into a few
issues along the way. The first is that Box.com apparently doesn't
like it if a directory has a dot in the name. No big deal, just use
foo instead of foo.git for a bare repository. Next, it gives 404
errors when you try to GET a URL with an extraneous query string.
Solution: use GIT_SMART_HTTP=0. Authentication is handled by libcurl
automatically reading .netrc. I've gotten to the point where I can
clone a repository, but pushing changes back to origin hangs followed
by timeout. I don't know if this bug is in git or libcurl, but I think
it's the former (as explained below).

Problem (see also attachment):
When you try to push changes to the remote, it hangs, followed by
erroring out with code 52, which is CURLE_GOT_NOTHING. Further
investigation shows that cURL successfully uses basic authentication
to GET a few files before trying a PROPFIND request on the
repository's root directory. The body of the request is in a separate
XML file asking the server about the supportedlock property.

The first time, cURL sends the request without authentication and
receives back 401 Unauthorized. The second time it tries the same
request using Basic authentication (this is the same pattern which
worked on the earlier GET requests). It gets back a 100-Continue, but
fails to upload the XML file like it did before (if you're following
along on the typescript, the verbose cURL output should say * We are
completely uploaded and fine). Instead it hangs for 60 seconds and
errors out with Empty reply from server.

I don't think this bug is in libcurl, since it successfully executes
all the other commands. I will try to investigate further, but I think
it has something to do with the multi-pass authentication. Attached is a
typescript of the behavior (editorial comments are placed inside [[ ]],
and all user info has been scrubbed). In case the attachment doesn't go
through, I have also pasted the typescript to gist [1]. If anyone else
wants to reproduce the bug, Box.com does offer a free account.

[1] 
https://gist.githubusercontent.com/abbaad/d4a8ba1e36000eeb8e02/raw/dd5b10ae42b1936d8da33bd384c9affdb103f686/typescript.txt

--
Abbaad Haider
abb...@gmail.com
$ git --version  uname -a  curl-config --version
git version 2.0.1
Linux localhost 3.15.3-1-ARCH #1 SMP PREEMPT Tue Jul 1 07:32:45 CEST 2014 
x86_64 GNU/Linux
libcurl 7.37.0
$ mkdir foo; cd foo
$ git --bare init
Initialized empty Git repository in /home/user/foo/
$ git update-server-info
$ cd ..
$ sudo mount -t davfs https://dav.box.com/dav ./box
$ cp -r foo box
$ sudo umount box
$ rm -r foo
$ cat  .netrc  EOF
 machine dav.box.com
 login [[ redacted ]]
 password [[ redacted ]]
 EOF
$ chmod 600 .netrc
$ GIT_SMART_HTTP=0 git clone https://dav.box.com/dav/foo
Cloning into 'foo'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.
$ cd foo/.git/hooks 
$ mv post-update.sample post-update
$ cd ../..
$ touch bar
$ git add .
$ git commit -a -m foo bar  
[master (root-commit) 2031b47] foo bar
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bar
$ GIT_SMART_HTTP=0 GIT_CURL_VERBOSE=1 GIT_TRACE=1 git push origin master
trace: built-in: git 'push' 'origin' 'master'
trace: run_command: 'git-remote-https' 'origin' 'https://dav.box.com/dav/foo'
* Hostname was NOT found in DNS cache
*   Trying 74.112.185.70...
* Connected to dav.box.com (74.112.185.70) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*subject: serialNumber=jde9iuVneOEaNkFotOvLFaWx0vb5-Qpv; C=US; 
ST=California; L=Los Altos; O=Box, Inc.; CN=*.box.com
*start date: 2014-04-07 05:14:35 GMT
*expire date: 2017-10-31 20:06:48 GMT
*subjectAltName: dav.box.com matched
*issuer: C=US; O=GeoTrust, Inc.; CN=GeoTrust SSL CA
*SSL certificate verify ok.
 GET /dav/foo/info/refs HTTP/1.1
User-Agent: git/2.0.1
Host: dav.box.com
Accept: */*
Accept-Encoding: gzip
Pragma: no-cache

 HTTP/1.1 401 Unauthorized
* Server nginx is not blacklisted
 Server: nginx
 Date: Fri, 04 Jul 2014 23:34:18 GMT
 Content-Type: application/xml; charset=utf-8
 Content-Length: 242
 Connection: keep-alive
 Vary: Host
 WWW-Authenticate: Basic realm=dav.box.com
 
* Ignoring the response-body
* Connection #0 to host dav.box.com left intact
* Issue another request to this URL: 'https://dav.box.com/dav/foo/info/refs'
* Found bundle for host dav.box.com: 0x123ff40
* Re-using existing connection! (#0) with host dav.box.com
* Connected to dav.box.com (74.112.185.70) port 443 (#0)
* Server auth using Basic with user '[[ redacted ]]'
 GET /dav/foo/info/refs HTTP/1.1
Authorization: Basic [[ redacted ]]
User-Agent: git/2.0.1
Host: dav.box.com
Accept: */*

[PATCH] http-push.c: make CURLOPT_IOCTLDATA a usable pointer

2014-07-05 Thread Abbaad Haider
Fixes a small bug affecting push to remotes which use some sort of
multi-pass authentication. In particular the bug affected SabreDAV as
configured by Box.com [1].

It must be a weird server configuration for the bug to have survived
this long. Someone should write a test for it.

[1] http://marc.info/?l=gitm=140460482604482

Signed-off-by: Abbaad Haider abb...@gmail.com
---
 http-push.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/http-push.c b/http-push.c
index f2c56c8..bd42895 100644
--- a/http-push.c
+++ b/http-push.c
@@ -199,7 +199,7 @@ static void curl_setup_http(CURL *curl, const char *url,
curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
 #ifndef NO_CURL_IOCTL
curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
-   curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer);
+   curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer);
 #endif
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
-- 
2.0.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/3] cache-tree: Create/update cache-tree on checkout

2014-07-05 Thread David Turner
On Tue, 2014-07-01 at 13:15 -0700, Junio C Hamano wrote:
 David Turner dtur...@twopensource.com writes:
 
  When git checkout checks out a branch, create or update the
  cache-tree so that subsequent operations are faster.
 
  Signed-off-by: David Turner dtur...@twitter.com
  ---
   builtin/checkout.c|  8 
   cache-tree.c  |  5 +++--
   t/t0090-cache-tree.sh | 15 ++-
   3 files changed, 25 insertions(+), 3 deletions(-)
 
  diff --git a/builtin/checkout.c b/builtin/checkout.c
  index 07cf555..a023a86 100644
  --- a/builtin/checkout.c
  +++ b/builtin/checkout.c
  @@ -553,6 +553,14 @@ static int merge_working_tree(const struct 
  checkout_opts *opts,
  }
  }
   
  +   if (!active_cache_tree)
  +   active_cache_tree = cache_tree();
  +
  +   if (!cache_tree_fully_valid(active_cache_tree))
  +   cache_tree_update(active_cache_tree,
  + (const struct cache_entry * const 
  *)active_cache,
  + active_nr, 0);
  +
 
 This looks much better than the previous round, but it still does
 allow verify_cache() to throw noises against unmerged entries in the
 cache, as WRITE_TREE_SILENT flag is not passed down, no?
 
   $ git checkout master^0
 $ git am $this_message
 $ make
 $ edit builtin/checkout.c ;# make changes to the above lines
 $ ./git checkout -m master^0
 x   builtin/checkout.c: unmerged 
 (972c8a7b28f16f88475268f9a714048c228e69db)
 x   builtin/checkout.c: unmerged 
 (f1dc56e55f7b2200412142b10517458ccfda2952)
 x   builtin/checkout.c: unmerged 
 (3b9753ba8c19e7dfe6e922f30eb85c83a92a4596)
 M   builtin/checkout.c
 Warning: you are leaving 1 commit behind, not connected to
 any of your branches:
 
   25fab54 cache-tree: Create/update cache-tree on checkout
 
 Switched to branch 'master'
 
 Passing WRITE_TREE_SILENT in the flags parameter will get rid of the
 conflict notice output from the above.
 
 The user is not interested in writing a brand new tree object at all
 in this case, so it feels wrong to actually let the call chain go
 down to update_one() and create new tree objects.
 
   Side note.  And passing WRITE_TREE_DRY_RUN is not a good
   solution either, because a later write_cache_as_tree() will
   not create the necessary tree object once you stuff a tree
   object name in the cache-tree.
 
 What we want in this code path is a way to repair a sub cache_tree
 if it can be repaired without creating a new tree object and
 otherwise leave that part invalid.  The existing cache-tree
 framework is not prepared to do that kind of thing.  It wants to
 start from the bottom and percolate things up, computing levels
 nearer to the top-level only after it fully created the trees for
 deeper levels, because it is meant to be used only when we really
 want to write out trees.  We may want to reuse update_one() but
 
 I am not convinced that doing an equivalent of write-tree when you
 switch branches is the right approach in the first place.  You will
 eventually write it out as a tree, and having a relatively undamaged
 cache-tree will help you when you do so, but spending the cycles
 necessary to compute a fully populated cache-tree, only to let it
 degrade over time until you are ready to write it out as a tree,
 somehow sounds like asking for a duplicated work upfront.

As I understand it, the cache-tree extension was originally designed to
speed up writing the tree later.  However, as Karsten Blees's work (and
my own tests) have shown, it also speeds up git status.  I use git
status a lot while working, and I've talked to a few others who do the
same.  So I think it's worth spending extra time when switching branches
to have a good working experience within that branch.

In the new version of the patchset (which I'll post shortly), I've added
an option WRITE_TREE_REPAIR, which does all of the work to compute a new
tree object, but only adds it to the cache-tree if it already exists
on-disk.  This is a little wasteful for the reason that you note.  So if
you would like, I could add a config option to skip it.  But I think it
is a good default.

Does this seem OK to you, assuming the implementation is good? 

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 4/4] cache-tree: Write updated cache-tree after commit

2014-07-05 Thread David Turner
During the commit process, update the cache-tree. Write this updated
cache-tree so that it's ready for subsequent commands.

Add test code which demonstrates that git commit now writes the cache
tree.  Make all tests test the entire cache-tree, not just the root
level.

Signed-off-by: David Turner dtur...@twitter.com
---
 builtin/commit.c  | 31 +++---
 t/t0090-cache-tree.sh | 87 ++-
 2 files changed, 91 insertions(+), 27 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 9cfef6c..5981755 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -342,6 +342,8 @@ static char *prepare_index(int argc, const char **argv, 
const char *prefix,
 
discard_cache();
read_cache_from(index_lock.filename);
+   if (update_main_cache_tree(WRITE_TREE_SILENT) = 0)
+   write_cache(fd, active_cache, active_nr);
 
commit_style = COMMIT_NORMAL;
return index_lock.filename;
@@ -363,10 +365,18 @@ 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);
-   if (write_cache(fd, active_cache, active_nr) ||
-   close_lock_file(index_lock))
-   die(_(unable to write new_index file));
+   if (active_cache_changed
+   || !cache_tree_fully_valid(active_cache_tree)) {
+   update_main_cache_tree(WRITE_TREE_SILENT);
+   active_cache_changed = 1;
+   }
+   if (active_cache_changed) {
+   if (write_cache(fd, active_cache, active_nr) ||
+   close_lock_file(index_lock))
+   die(_(unable to write new_index file));
+   } else {
+   rollback_lock_file(index_lock);
+   }
commit_style = COMMIT_NORMAL;
return index_lock.filename;
}
@@ -383,14 +393,10 @@ static char *prepare_index(int argc, const char **argv, 
const char *prefix,
if (!only  !pathspec.nr) {
fd = hold_locked_index(index_lock, 1);
refresh_cache_or_die(refresh_flags);
-   if (active_cache_changed) {
-   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));
-   } else {
-   rollback_lock_file(index_lock);
-   }
+   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));
commit_style = COMMIT_AS_IS;
return get_index_file();
}
@@ -435,6 +441,7 @@ static char *prepare_index(int argc, const char **argv, 
const char *prefix,
fd = hold_locked_index(index_lock, 1);
add_remove_files(partial);
refresh_cache(REFRESH_QUIET);
+   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));
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 8437c5f..15f1484 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -7,8 +7,14 @@ cache-tree extension.
 
  . ./test-lib.sh
 
+grep_nonmatch_ok () {
+grep $@
+test $? = 2  return 1
+return 0
+}
+
 cmp_cache_tree () {
-   test-dump-cache-tree actual 
+   test-dump-cache-tree | grep_nonmatch_ok -v \#\(ref\) actual 
sed s/$_x40/SHA/ actual filtered 
test_cmp $1 filtered
 }
@@ -16,15 +22,33 @@ cmp_cache_tree () {
 # We don't bother with actually checking the SHA1:
 # test-dump-cache-tree already verifies that all existing data is
 # correct.
-test_shallow_cache_tree () {
-   printf SHA  (%d entries, 0 subtrees)\n $(git ls-files|wc -l) expect 

+generate_expected_cache_tree () {
+   dir=$1${1:+/} 
+   parent=$2 
+   # ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux
+   # We want to count only foo because it's the only direct child
+   subtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) 
+   subtree_count=$(echo $subtrees|grep_nonmatch_ok -c .) 
+   entries=$(git ls-files|wc -l) 
+   printf SHA $dir (%d entries, %d subtrees)\n $entries $subtree_count 
+   for subtree in $subtrees
+   do
+   cd $subtree
+   generate_expected_cache_tree 

[PATCH v4 3/4] cache-tree: subdirectory tests

2014-07-05 Thread David Turner
Add tests to confirm that invalidation of subdirectories nether over-
nor under-invalidates.

Signed-off-by: David Turner dtur...@twitter.com
---
 t/t0090-cache-tree.sh | 28 +---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 98fb1ab..8437c5f 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -21,10 +21,13 @@ test_shallow_cache_tree () {
cmp_cache_tree expect
 }
 
+# Test that the cache-tree for a given directory is invalid.
+# If no directory is given, check that the root is invalid
 test_invalid_cache_tree () {
-   echo invalid   (0 subtrees) expect 
-   printf SHA #(ref)  (%d entries, 0 subtrees)\n $(git ls-files|wc -l) 
expect 
-   cmp_cache_tree expect
+   test-dump-cache-tree actual 
+   sed -e s/$_x40/SHA/ -e s/[0-9]* subtrees//g actual filtered 
+   expect=$(printf invalid  $1 ()\n) 
+   fgrep $expect filtered
 }
 
 test_no_cache_tree () {
@@ -49,6 +52,25 @@ test_expect_success 'git-add invalidates cache-tree' '
test_invalid_cache_tree
 '
 
+test_expect_success 'git-add in subdir invalidates cache-tree' '
+   test_when_finished git reset --hard; git read-tree HEAD 
+   mkdir dirx 
+   echo I changed this file dirx/foo 
+   git add dirx/foo 
+   test_invalid_cache_tree
+'
+
+test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' 
'
+   git tag no-children 
+   test_when_finished git reset --hard no-children; git read-tree HEAD 
+   mkdir dir1 dir2 
+   test_commit dir1/a 
+   test_commit dir2/b 
+   echo I changed this file dir1/a 
+   git add dir1/a 
+   test_invalid_cache_tree dir1/
+'
+
 test_expect_success 'update-index invalidates cache-tree' '
test_when_finished git reset --hard; git read-tree HEAD 
echo I changed this file foo 
-- 
2.0.0.390.gcb682f8

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 1/4] cache-tree: Create/update cache-tree on checkout

2014-07-05 Thread David Turner
When git checkout checks out a branch, create or update the
cache-tree so that subsequent operations are faster.

update_main_cache_tree learned a new flag, WRITE_TREE_REPAIR.  When
WRITE_TREE_REPAIR is set, portions of the cache-tree which do not
correspond to existing tree objects are invalidated (and portions which
do are marked as valid).  No new tree objects are created.

Signed-off-by: David Turner dtur...@twitter.com
---
 builtin/checkout.c|  8 
 cache-tree.c  | 12 +++-
 cache-tree.h  |  1 +
 t/t0090-cache-tree.sh | 19 ---
 4 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 07cf555..054214f 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -553,6 +553,14 @@ static int merge_working_tree(const struct checkout_opts 
*opts,
}
}
 
+   if (!active_cache_tree)
+   active_cache_tree = cache_tree();
+
+   if (!cache_tree_fully_valid(active_cache_tree))
+   cache_tree_update(active_cache_tree,
+ (const struct cache_entry * const 
*)active_cache,
+ active_nr, WRITE_TREE_SILENT | 
WRITE_TREE_REPAIR);
+
if (write_cache(newfd, active_cache, active_nr) ||
commit_locked_index(lock_file))
die(_(unable to write new index file));
diff --git a/cache-tree.c b/cache-tree.c
index 7fa524a..f951d7d 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -239,9 +239,12 @@ static int update_one(struct cache_tree *it,
struct strbuf buffer;
int missing_ok = flags  WRITE_TREE_MISSING_OK;
int dryrun = flags  WRITE_TREE_DRY_RUN;
+   int repair = flags  WRITE_TREE_REPAIR;
int to_invalidate = 0;
int i;
 
+   assert(!(dryrun  repair));
+
*skip_count = 0;
 
if (0 = it-entry_count  has_sha1_file(it-sha1))
@@ -374,7 +377,14 @@ static int update_one(struct cache_tree *it,
 #endif
}
 
-   if (dryrun)
+   if (repair) {
+   unsigned char sha1[20];
+   hash_sha1_file(buffer.buf, buffer.len, tree_type, sha1);
+   if (has_sha1_file(sha1))
+   hashcpy(it-sha1, sha1);
+   else
+   to_invalidate = 1;
+   } else if (dryrun)
hash_sha1_file(buffer.buf, buffer.len, tree_type, it-sha1);
else if (write_sha1_file(buffer.buf, buffer.len, tree_type, it-sha1)) {
strbuf_release(buffer);
diff --git a/cache-tree.h b/cache-tree.h
index f1923ad..666d18f 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -39,6 +39,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_REPAIR 16
 
 /* error return codes */
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 6c33e28..98fb1ab 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -44,14 +44,14 @@ test_expect_success 'read-tree HEAD establishes cache-tree' 
'
 
 test_expect_success 'git-add invalidates cache-tree' '
test_when_finished git reset --hard; git read-tree HEAD 
-   echo I changed this file  foo 
+   echo I changed this file foo 
git add foo 
test_invalid_cache_tree
 '
 
 test_expect_success 'update-index invalidates cache-tree' '
test_when_finished git reset --hard; git read-tree HEAD 
-   echo I changed this file  foo 
+   echo I changed this file foo 
git update-index --add foo 
test_invalid_cache_tree
 '
@@ -85,9 +85,22 @@ test_expect_success 'reset --hard without index gives 
cache-tree' '
test_shallow_cache_tree
 '
 
-test_expect_failure 'checkout gives cache-tree' '
+test_expect_success 'checkout gives cache-tree' '
+   git tag current 
git checkout HEAD^ 
test_shallow_cache_tree
 '
 
+test_expect_success 'checkout -b gives cache-tree' '
+   git checkout current 
+   git checkout -b prev HEAD^ 
+   test_shallow_cache_tree
+'
+
+test_expect_success 'checkout -B gives cache-tree' '
+   git checkout current 
+   git checkout -B prev HEAD^ 
+   test_shallow_cache_tree
+'
+
 test_done
-- 
2.0.0.390.gcb682f8

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/4] test-dump-cache-tree: invalid trees are not errors

2014-07-05 Thread David Turner
Do not treat known-invalid trees as errors even when their count is
incorrect.  Because git already knows that these trees are invalid,
nothing depends on the count field.

Add a couple of comments.

Signed-off-by: David Turner dtur...@twitter.com
---
 test-dump-cache-tree.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test-dump-cache-tree.c b/test-dump-cache-tree.c
index 47eab97..cbbbd8e 100644
--- a/test-dump-cache-tree.c
+++ b/test-dump-cache-tree.c
@@ -26,16 +26,16 @@ static int dump_cache_tree(struct cache_tree *it,
return 0;
 
if (it-entry_count  0) {
+   /* invalid */
dump_one(it, pfx, );
dump_one(ref, pfx, #(ref) );
-   if (it-subtree_nr != ref-subtree_nr)
-   errs = 1;
}
else {
dump_one(it, pfx, );
if (hashcmp(it-sha1, ref-sha1) ||
ref-entry_count != it-entry_count ||
ref-subtree_nr != it-subtree_nr) {
+   /* claims to be valid but is lying */
dump_one(ref, pfx, #(ref) );
errs = 1;
}
-- 
2.0.0.390.gcb682f8

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html