Continuing the endless RFCs of sparse checkout, this series drops the sparse hook
in favor of .git/info/sparse. Changes from the last version
Prevent diff machinery from examining assume-unchanged entries on worktree
"if (ce_uptodate(ce) || CE_VALID)" is updated, as well as the corresponding test
Avoid writing to buffer in add_excludes_from_file_1()
Splitted out from the old second patch, as suggested by Johannes
Read .gitignore from index if it is assume-unchanged
read_index_data() is renamed. Commit message mentions add_excludes_from_file()
excluded_1(): support exclude "directories" in index
This one is new because index does not have "directory", more comments in the patch
dir.c: export excluded_1() and add_excludes_from_file_1()
New too, exported for use in unpack-trees.c
unpack-trees.c: generalize verify_* functions
Splitted out of the old third patch for easier review
Support sparse checkout in unpack_trees() and read-tree
Read .git/info/sparse instead of .git/hooks/sparse
--sparse for porcelains
RFC patch
Documentation/technical/api-directory-listing.txt | 3 +
builtin-checkout.c | 4 +
builtin-clean.c | 5 +-
builtin-ls-files.c | 4 +-
builtin-merge.c | 5 +-
builtin-read-tree.c | 4 +-
cache.h | 3 +
diff-lib.c | 6 +-
dir.c | 101 +++++++++++------
dir.h | 4 +
git-pull.sh | 6 +-
t/t1009-read-tree-sparse.sh | 47 ++++++++
t/t3001-ls-files-others-exclude.sh | 22 ++++
t/t4039-diff-assume-unchanged.sh | 31 ++++++
t/t7300-clean.sh | 19 ++++
unpack-trees.c | 121 ++++++++++++++++++++-
unpack-trees.h | 3 +
17 files changed, 340 insertions(+), 48 deletions(-)
create mode 100755 t/t1009-read-tree-sparse.sh
create mode 100755 t/t4039-diff-assume-unchanged.sh
@@ -162,7 +162,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)if(ce_uptodate(ce))continue;-changed=check_removed(ce,&st);+/* If CE_VALID is set, don't look at workdir for file removal */+changed=(ce->ce_flags&CE_VALID)?0:check_removed(ce,&st);if(changed){if(changed<0){perror(ce->name);
@@ -337,6 +338,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,structrev_info*revs=o->unpack_data;intmatch_missing,cached;+/* if the entry is not checked out, don't examine work tree */+cached=o->index_only||(idx&&(idx->ce_flags&CE_VALID));/**Backwardcompatibilitywart-"diff-index -m"does*notmean"do not ignore merges",but"match_missing".
@@ -0,0 +1,31 @@+#!/bin/sh++test_description='diff with assume-unchanged entries'++../test-lib.sh++# external diff has been tested in t4020-diff-external.sh++test_expect_success'setup''+echozero>zero&&+gitaddzero&&+gitcommit-mzero&&+echoone>one&&+echotwo>two&&+gitaddonetwo&&+gitcommit-monetwo&&+gitupdate-index--assume-unchangedone&&+echoborked>>one&&+test"$(gitls-files-vone)"="h one"+'++test_expect_success'diff-index does not examine assume-unchanged entries''+gitdiff-indexHEAD^--one|grep-q5626abf0f72e58d7a153368ba57db4c673c0e171+'++test_expect_success'diff-files does not examine assume-unchanged entries''+rmone&&+test-z"$(gitdiff-files--one)"+'++test_done
In the next patch, the buffer that is being used within
add_excludes_from_file_1() comes from another function and does not
have extra space to put \n at the end.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
dir.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
Index does not really have "directories", attempts to match "foo/"
against index will fail unless someone tries to reconstruct directories
from a list of file.
Observing that dtype in this function can never be NULL (otherwise
it would segfault), dtype NULL will be used to say "hey.. you are
matching against index" and behave properly.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
Having dtype to segfault when dtype is NULL is nice, but I found
no way else to sneak the new code in. Defining DT_INDEX may clash
existing system definitions..
dir.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
In sparse checkout mode (aka CE_VALID or assume-unchanged) some files
may be missing from working directory. If some of those files are
.gitignore, it will affect how git excludes files.
Because those files are by definition "assume unchanged" we can
instead read them from index. This adds index as a prerequisite for
directory listing. At the moment directory listing is used by "git
clean", "git add", "git ls-files" and "git status"/"git commit" and
unpack_trees()-related commands. These commands have been
checked/modified to populate index before doing directory listing.
add_excludes_from_file() does not enable this feature, because it
is used to read .git/info/exclude and some explicit files specified
by "git ls-files".
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
Documentation/technical/api-directory-listing.txt | 3 +
builtin-clean.c | 5 +-
builtin-ls-files.c | 4 +-
dir.c | 66 ++++++++++++++------
t/t3001-ls-files-others-exclude.sh | 22 +++++++
t/t7300-clean.sh | 19 ++++++
6 files changed, 97 insertions(+), 22 deletions(-)
@@ -58,6 +58,9 @@ The result of the enumeration is left in these fields:: Calling sequence ----------------+* Ensure the_index is populated as it may have CE_VALID entries that+ affect directory listing.+ * Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0, sizeof(dir))`.
@@ -508,7 +511,6 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)pathspec=get_pathspec(prefix,argv);/* be nice with submodule paths ending in a slash */-read_cache();if(pathspec)strip_trailing_slash_from_submodules();
@@ -200,11 +200,36 @@ void add_exclude(const char *string, const char *base,which->excludes[which->nr++]=x;}+staticvoid*read_assume_unchanged_from_index(constchar*path,size_t*size)+{+intpos,len;+unsignedlongsz;+enumobject_typetype;+void*data;+structindex_state*istate=&the_index;++len=strlen(path);+pos=index_name_pos(istate,path,len);+if(pos<0)+returnNULL;+/* only applies to CE_VALID entries */+if(!(istate->cache[pos]->ce_flags&CE_VALID))+returnNULL;+data=read_sha1_file(istate->cache[pos]->sha1,&type,&sz);+if(!data||type!=OBJ_BLOB){+free(data);+returnNULL;+}+*size=xsize_t(sz);+returndata;+}+staticintadd_excludes_from_file_1(constchar*fname,constchar*base,intbaselen,char**buf_p,-structexclude_list*which)+structexclude_list*which,+intcheck_index){structstatst;intfd,i;
@@ -212,20 +237,26 @@ static int add_excludes_from_file_1(const char *fname,char*buf,*entry;fd=open(fname,O_RDONLY);-if(fd<0||fstat(fd,&st)<0)-gotoerr;-size=xsize_t(st.st_size);-if(size==0){-close(fd);-return0;+if(fd<0||fstat(fd,&st)<0){+if(0<=fd)+close(fd);+if(!check_index||+(buf=read_assume_unchanged_from_index(fname,&size))==NULL)+return-1;}-buf=xmalloc(size+1);-if(read_in_full(fd,buf,size)!=size)-{-free(buf);-gotoerr;+else{+size=xsize_t(st.st_size);+if(size==0){+close(fd);+return0;+}+buf=xmalloc(size);+if(read_in_full(fd,buf,size)!=size){+close(fd);+return-1;+}+close(fd);}-close(fd);if(buf_p)*buf_p=buf;
@@ -240,17 +271,12 @@ static int add_excludes_from_file_1(const char *fname,}}return0;--err:-if(0<=fd)-close(fd);-return-1;}voidadd_excludes_from_file(structdir_struct*dir,constchar*fname){if(add_excludes_from_file_1(fname,"",0,NULL,-&dir->exclude_list[EXC_FILE])<0)+&dir->exclude_list[EXC_FILE],0)<0)die("cannot use %s as an exclude file",fname);}
These functions are used to handle .gitignore. They are now exported
so that sparse checkout can reuse.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
dir.c | 32 ++++++++++++++++----------------
dir.h | 4 ++++
2 files changed, 20 insertions(+), 16 deletions(-)
@@ -275,8 +275,8 @@ static int add_excludes_from_file_1(const char *fname,voidadd_excludes_from_file(structdir_struct*dir,constchar*fname){-if(add_excludes_from_file_1(fname,"",0,NULL,-&dir->exclude_list[EXC_FILE],0)<0)+if(add_excludes_from_file_to_list(fname,"",0,NULL,+&dir->exclude_list[EXC_FILE],0)<0)die("cannot use %s as an exclude file",fname);}
@@ -337,9 +337,9 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)/* Scan the list and let the last match determine the fate.*Return1forexclude,0forincludeand-1forundecided.*/-staticintexcluded_1(constchar*pathname,-intpathlen,constchar*basename,int*dtype,-structexclude_list*el)+intexcluded_from_list(constchar*pathname,+intpathlen,constchar*basename,int*dtype,+structexclude_list*el){inti;
@@ -413,8 +413,8 @@ int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)prep_exclude(dir,pathname,basename-pathname);for(st=EXC_CMDL;st<=EXC_FILE;st++){-switch(excluded_1(pathname,pathlen,basename,-dtype_p,&dir->exclude_list[st])){+switch(excluded_from_list(pathname,pathlen,basename,+dtype_p,&dir->exclude_list[st])){case0:return0;case1:
This patch makes unpack_trees() look at .git/info/sparse [1] to
determine which files should stay in working directory, after
merging, by:
- setting CE_VALID properly so that other operations correctly ignore
missing files
- driving check_updates() to add/remove files in accordance to
CE_VALID
The feature is disabled by default. Use "read-tree --sparse" to enable it.
[1] .git/info/sparse has the same syntax as .git/info/exclude. Files
that match the patterns will be set as CE_VALID.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
builtin-read-tree.c | 4 +-
cache.h | 3 +
t/t1009-read-tree-sparse.sh | 47 ++++++++++++++++++++
unpack-trees.c | 98 ++++++++++++++++++++++++++++++++++++++++++-
unpack-trees.h | 3 +
5 files changed, 153 insertions(+), 2 deletions(-)
create mode 100755 t/t1009-read-tree-sparse.sh
@@ -98,6 +98,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)PARSE_OPT_NONEG,exclude_per_directory_cb},OPT_SET_INT('i',NULL,&opts.index_only,"don't check the working tree after merging",1),+OPT_SET_INT(0,"sparse",&opts.apply_sparse,+"apply sparse checkout filter",1),OPT_END()};
@@ -177,6 +177,9 @@ struct cache_entry {#define CE_HASHED (0x100000)#define CE_UNHASHED (0x200000)+/* Only remove in work directory, not index */+#define CE_WT_REMOVE (0x400000)+/**Extendedon-diskflags*/
@@ -0,0 +1,47 @@+#!/bin/sh++test_description='sparse checkout tests'++../test-lib.sh++test_expect_success'setup''+test_commitone&&+mkdirtwo&&+test_committwotwo/two.ttwo.t+'++test_expect_success'read-tree without .git/info/sparse''+gitread-tree--sparse-m-uHEAD&&+test-fone.t&&+test-ftwo/two.t+'++test_expect_success'read-tree with empty .git/info/sparse''+echo>.git/info/sparse&&+gitread-tree--sparse-m-uHEAD&&+test-fone.t&&+test-ftwo/two.t+'++test_expect_success'read-tree --sparse''+echo"one.t">.git/info/sparse&&+gitread-tree--sparse-m-uHEAD&&+test!-fone.t&&+test-ftwo/two.t+'++test_expect_success'read-tree --sparse foo where foo is "directory"''+echo"two">.git/info/sparse&&+gitread-tree--sparse-m-uHEAD&&+test-fone.t&&+test-ftwo/two.t+'++test_expect_success'read-tree --sparse foo/''+echo"two/">.git/info/sparse&&+gitread-tree--sparse-m-uHEAD&&+test-fone.t&&+test!-ftwo/two.t+'++test_done
@@ -32,6 +32,12 @@ static struct unpack_trees_error_msgs unpack_plumbing_errors = {/* bind_overlap */"Entry '%s' overlaps with '%s'. Cannot bind.",++/* sparse_not_uptodate_file */+"Entry '%s' not uptodate. Cannot update sparse checkout.",++/* would_lose_orphaned */+"Working tree file '%s' would be %s by sparse checkout update.",};#define ERRORMSG(o,fld) \
@@ -78,7 +84,7 @@ static int check_updates(struct unpack_trees_options *o)if(o->update&&o->verbose_update){for(total=cnt=0;cnt<index->cache_nr;cnt++){structcache_entry*ce=index->cache[cnt];-if(ce->ce_flags&(CE_UPDATE|CE_REMOVE))+if(ce->ce_flags&(CE_UPDATE|CE_REMOVE|CE_WT_REMOVE))total++;}
@@ -92,6 +98,13 @@ static int check_updates(struct unpack_trees_options *o)for(i=0;i<index->cache_nr;i++){structcache_entry*ce=index->cache[i];+if(ce->ce_flags&CE_WT_REMOVE){+display_progress(progress,++cnt);+if(o->update)+unlink_entry(ce);+continue;+}+if(ce->ce_flags&CE_REMOVE){display_progress(progress,++cnt);if(o->update)
@@ -118,6 +131,74 @@ static int check_updates(struct unpack_trees_options *o)returnerrs!=0;}+staticintverify_uptodate_sparse(structcache_entry*ce,structunpack_trees_options*o);+staticintverify_absent_sparse(structcache_entry*ce,constchar*action,structunpack_trees_options*o);+staticintapply_sparse_checkout(structunpack_trees_options*o)+{+structindex_state*index=&o->result;+structexclude_listel;+inti,ret=0;++memset(&el,0,sizeof(el));+if(add_excludes_from_file_to_list(git_path("info/sparse"),"",0,NULL,&el,0)<0)+return0;++for(i=0;i<index->cache_nr;i++){+structcache_entry*ce=index->cache[i];+constchar*basename;+intwas_valid=ce->ce_flags&CE_VALID;++if(ce_stage(ce))+continue;++basename=strrchr(ce->name,'/');+basename=basename?basename+1:ce->name;+if(excluded_from_list(ce->name,ce_namelen(ce),basename,NULL,&el)>0)+ce->ce_flags|=CE_VALID;+else+ce->ce_flags&=~CE_VALID;++/*+*Weonlycareaboutfilesgettingintothecheckoutarea+*Ifmergestrategieswanttoremovesome,goahead+*/+if(ce->ce_flags&CE_REMOVE)+continue;++if(!was_valid&&(ce->ce_flags&CE_VALID)){+/*+*IfCE_UPDATEisset,verify_uptodate()mustbecalledalready+*alsostatinfomayhavelostaftermerged_entry()socalling+*verify_uptodate()againmayfail+*/+if(!(ce->ce_flags&CE_UPDATE)&&verify_uptodate_sparse(ce,o)){+ret=-1;+break;+}+ce->ce_flags|=CE_WT_REMOVE;+}+if(was_valid&&!(ce->ce_flags&CE_VALID)){+if(verify_absent_sparse(ce,"overwritten",o)){+ret=-1;+break;+}+ce->ce_flags|=CE_UPDATE;+}++/* merge strategies may set CE_UPDATE outside checkout area */+if(ce->ce_flags&CE_VALID)+ce->ce_flags&=~CE_UPDATE;++}++for(i=0;i<el.nr;i++)+free(el.excludes[i]);+if(el.excludes)+free(el.excludes);++returnret;+}+staticinlineintcall_unpack_fn(structcache_entry**src,structunpack_trees_options*o){intret=o->fn(src,o);
This series is useless until now because no one would use read-tree to
checkout. At least with this, you can really use/test the series.
Porcelain design was originally "if you have .git/info/sparse,
porcelains will use it, if you don't like that, remove
.git/info/sparse" while plumblings have an option to
enable/disable this feature.
And I still like that behavior. How about we enable sparse checkout
by default for porcelains and make a config option to disable it?
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
builtin-checkout.c | 4 ++++
builtin-merge.c | 5 ++++-
git-pull.sh | 6 +++++-
3 files changed, 13 insertions(+), 2 deletions(-)
@@ -172,6 +172,7 @@ static struct option builtin_merge_options[] = {OPT_CALLBACK('m',"message",&merge_msg,"message","message to be used for the merge commit (if any)",option_parse_message),+OPT_SET_INT(0,"sparse",&apply_sparse,"apply sparse checkout filter",1),OPT__VERBOSITY(&verbosity),OPT_END()};
[1] .git/info/sparse has the same syntax as .git/info/exclude. Files
that match the patterns will be set as CE_VALID.
Does this mean it will only support excluding paths you don't want
rather than letting you only include paths you do want?
I'm currently using your other patch series that lets you include or
exclude paths (via config variable) and I find that I mostly use the
include side of it with only a few excluded paths. This is because I
typically want to include only a small subset of the repository so
using excludes would require a pretty large list and any time somebody
adds new files, I'd have to update the exclude list.
I appreciate the flexibility of the script to control what is included
or excluded, but like some other comments here, I like the simplicity
of having built-in support for including/excluding paths without
having to write a script to do it. Some of my projects run on Windows
so scripting is more difficult there.
From: Jakub Narebski <hidden> Date: 2016-06-15 22:47:13
skillzero@gmail.com writes:
2009/8/11 Nguyễn Thái Ngọc Duy [off-list ref]:
quoted
[1] .git/info/sparse has the same syntax as .git/info/exclude. Files
that match the patterns will be set as CE_VALID.
Does this mean it will only support excluding paths you don't want
rather than letting you only include paths you do want?
Errr... what I read is that paths set by .git/info/sparse would be
excluded from checkout (marked as assume-unchanged / CE_VALID).
But if it is the same mechanism as gitignore, then you can use !
prefix to set files (patterns) to include, e.g.
!Documentation/
*
(I think rules are processed top-down, first matching wins).
I'm currently using your other patch series that lets you include or
exclude paths (via config variable) and I find that I mostly use the
include side of it with only a few excluded paths. This is because I
typically want to include only a small subset of the repository so
using excludes would require a pretty large list and any time somebody
adds new files, I'd have to update the exclude list.
On Tue, Aug 11, 2009 at 2:38 PM, Jakub Narebski[off-list ref] wrote:
skillzero@gmail.com writes:
quoted
2009/8/11 Nguyễn Thái Ngọc Duy [off-list ref]:
quoted
quoted
[1] .git/info/sparse has the same syntax as .git/info/exclude. Files
that match the patterns will be set as CE_VALID.
Does this mean it will only support excluding paths you don't want
rather than letting you only include paths you do want?
Errr... what I read is that paths set by .git/info/sparse would be
excluded from checkout (marked as assume-unchanged / CE_VALID).
But if it is the same mechanism as gitignore, then you can use !
prefix to set files (patterns) to include, e.g.
!Documentation/
*
(I think rules are processed top-down, first matching wins).
I wasn't sure because the .gitignore negation stuff mentions negating
a previously ignored pattern. But for sparse patterns, there likely
wouldn't be a previous pattern. Include patterns are a little
different in that if there are no include patterns (but maybe some
exclude patterns), I think the expectation is that everything will be
included (minus excludes), but if you have some include patterns then
only those paths will be included (minus any excludes).
It's great if it already supports includes as well as excludes
(although it's a little confusing to say !Documentation to mean
"include it"), but I wasn't sure from the comment so I was just
asking.
On Wed, Aug 12, 2009 at 5:03 AM, [off-list ref] wrote:
On Tue, Aug 11, 2009 at 2:38 PM, Jakub Narebski[off-list ref] wrote:
quoted
skillzero@gmail.com writes:
quoted
2009/8/11 Nguyễn Thái Ngọc Duy [off-list ref]:
quoted
quoted
[1] .git/info/sparse has the same syntax as .git/info/exclude. Files
that match the patterns will be set as CE_VALID.
Does this mean it will only support excluding paths you don't want
rather than letting you only include paths you do want?
Errr... what I read is that paths set by .git/info/sparse would be
excluded from checkout (marked as assume-unchanged / CE_VALID).
But if it is the same mechanism as gitignore, then you can use !
prefix to set files (patterns) to include, e.g.
!Documentation/
*
(I think rules are processed top-down, first matching wins).
I wasn't sure because the .gitignore negation stuff mentions negating
a previously ignored pattern. But for sparse patterns, there likely
wouldn't be a previous pattern.
No problem. We put pattern '*' at top (match everything). Previous
pattern issue solved.
Include patterns are a little
different in that if there are no include patterns (but maybe some
exclude patterns), I think the expectation is that everything will be
included (minus excludes), but if you have some include patterns then
only those paths will be included (minus any excludes).
Let's say you want to include foo/ and bar/ only, this should work:
*
!foo/
!bar/
The evaluating order is from bottom up. When it first matches 'bar/',
because it a negate pattern, it returns "no don't match" and stops.
When it matches neither foo/ nor bar/ then it will be caught by '*'
and return "yes it matches" - that means "ignored" from checkout area.
In the end only foo/* and bar/* survive.
I think it's as easy as writing exclude patterns once you figure out '*'.
--
Duy
@@ -58,6 +58,9 @@ The result of the enumeration is left in these fields:: Calling sequence ----------------+* Ensure the_index is populated as it may have CE_VALID entries that+ affect directory listing.+
When you want to enumerate all paths in the work tree, instead of not just
the untracked ones, it used to be possible to first run read_directory()
before calling read_cache(). You are now forbidding this.
I do not think it is hard to resurrect the feature if it is necessary (add
an option to dir_struct and teach dir_add_name() not to ignore paths the
index knows about), and I do not think none of the existing code relies on
it anymore (I think "git add" used to), but there may be some codepath I
forgot about, which is a concern.
Wouldn't it be much cleaner to move the existing read_cache() up, like you
did for ls-files, instead of conditionally reading the index at a random
place in the program sequence depending on the combinations of options?
From: Johannes Sixt <hidden> Date: 2016-06-15 22:47:13
Nguyễn Thái Ngọc Duy schrieb:
This series is useless until now because no one would use read-tree to
checkout. At least with this, you can really use/test the series.
Porcelain design was originally "if you have .git/info/sparse,
porcelains will use it, if you don't like that, remove
.git/info/sparse" while plumblings have an option to
enable/disable this feature.
And I still like that behavior. How about we enable sparse checkout
by default for porcelains and make a config option to disable it?
I would enable sparse checkout by default even for plumbing. Whether the
checkout area is sparse should always be governed by .git/info/sparse.
This way, existing scripts and aliases should automatically work in sparse
worktrees.
BTW, the name .git/info/sparse is perhaps a bit too technical in the sense
that only git developers know that this feature runs under the name
"sparse checkout". Perhaps it should be named
.git/info/indexonly
.git/info/nocheckout
or so.
-- Hannes
BTW, the name .git/info/sparse is perhaps a bit too technical in the sense
that only git developers know that this feature runs under the name
"sparse checkout". Perhaps it should be named
.git/info/indexonly
.git/info/nocheckout
or so.
I did not like the name "sparse" either. Another option is
.git/info/assume-unchanged.
--
Duy
From: Raja R Harinath <hidden> Date: 2016-06-15 22:47:13
Hi,
Nguyen Thai Ngoc Duy [off-list ref] writes:
2009/8/12 Johannes Sixt [off-list ref]:
quoted
BTW, the name .git/info/sparse is perhaps a bit too technical in the sense
that only git developers know that this feature runs under the name
"sparse checkout". Perhaps it should be named
.git/info/indexonly
.git/info/nocheckout
or so.
I did not like the name "sparse" either. Another option is
.git/info/assume-unchanged.
Or .git/info/doppelgangers, or even .git/info/doppelgängers :-)
- Hari
@@ -58,6 +58,9 @@ The result of the enumeration is left in these fields::
Calling sequence
----------------
+* Ensure the_index is populated as it may have CE_VALID entries that
+ affect directory listing.
+
When you want to enumerate all paths in the work tree, instead of not just
the untracked ones, it used to be possible to first run read_directory()
before calling read_cache(). You are now forbidding this.
Either I phrased it badly, or I don't follow you. If you don't call
read_cache() before read_directory(), the_index should be empty and
read_assume_unchanged_from_index() will be no-op. So read_directory()
behavior does not change in this case.
I do not think it is hard to resurrect the feature if it is necessary (add
an option to dir_struct and teach dir_add_name() not to ignore paths the
index knows about), and I do not think none of the existing code relies on
it anymore (I think "git add" used to), but there may be some codepath I
forgot about, which is a concern.
Hmm.. "git add" loaded index early since the first version of
builtin-add.c. I have checked all code path that can lead to
read_directory_recursively(). In all cases, index is loaded before
read_dir..() is called.
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
- if (!ignored)
+ if (!ignored) {
+ if (read_cache() < 0)
+ die("index file corrupt");
setup_standard_excludes(&dir);
+ }
pathspec = get_pathspec(prefix, argv);
read_cache();
Wouldn't it be much cleaner to move the existing read_cache() up, like you
did for ls-files, instead of conditionally reading the index at a random
place in the program sequence depending on the combinations of options?
Agreed. read_cache() is called right below anyway.
--
Duy
From: Johannes Sixt <hidden> Date: 2016-06-15 22:47:14
Raja R Harinath schrieb:
Hi,
Nguyen Thai Ngoc Duy [off-list ref] writes:
quoted
2009/8/12 Johannes Sixt [off-list ref]:
quoted
BTW, the name .git/info/sparse is perhaps a bit too technical in the sense
that only git developers know that this feature runs under the name
"sparse checkout". Perhaps it should be named
.git/info/indexonly
.git/info/nocheckout
or so.
I did not like the name "sparse" either. Another option is
.git/info/assume-unchanged.
Or .git/info/doppelgangers, or even .git/info/doppelgängers :-)
Heh!
.git/info/phantoms
git checkout --no-phantoms
git read-tree --phantoms
-- Hannes