The on-disk format of index only saves 16 bit flags, nearly all have
been used. The last bit (CE_EXTENDED) is used to for future extension.
This patch extends index entry format to save more flags in future.
The new entry format will be used when CE_EXTENDED bit is 1.
Because older implementation may not understand CE_EXTENDED bit and
misread the new format, if there is any extended entry in index, index
header version will turn 3, which makes it incompatible for older git.
If there is none, header version will return to 2 again.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
cache.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
read-cache.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 95 insertions(+), 14 deletions(-)
@@ -1096,7 +1096,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)if(hdr->hdr_signature!=htonl(CACHE_SIGNATURE))returnerror("bad signature");-if(hdr->hdr_version!=htonl(2))+if(hdr->hdr_version!=htonl(2)&&hdr->hdr_version!=htonl(3))returnerror("bad index version");SHA1_Init(&c);SHA1_Update(&c,hdr,size-20);
@@ -1131,6 +1131,7 @@ int read_index(struct index_state *istate)staticvoidconvert_from_disk(structondisk_cache_entry*ondisk,structcache_entry*ce){size_tlen;+constchar*name;ce->ce_ctime=ntohl(ondisk->ctime.sec);ce->ce_mtime=ntohl(ondisk->mtime.sec);
@@ -1143,19 +1144,31 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en/* On-disk flags are just 16 bits */ce->ce_flags=ntohs(ondisk->flags);-/* For future extension: we do not understand this entry yet */-if(ce->ce_flags&CE_EXTENDED)-die("Unknown index entry format");hashcpy(ce->sha1,ondisk->sha1);len=ce->ce_flags&CE_NAMEMASK;++if(ce->ce_flags&CE_EXTENDED){+structondisk_cache_entry_extended*ondisk2;+intextended_flags;+ondisk2=(structondisk_cache_entry_extended*)ondisk;+extended_flags=ntohs(ondisk2->flags2)<<16;+/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */+if(extended_flags&~CE_EXTENDED_FLAGS)+die("Unknown index entry format %08x",extended_flags);+ce->ce_flags|=extended_flags;+name=ondisk2->name;+}+else+name=ondisk->name;+if(len==CE_NAMEMASK)-len=strlen(ondisk->name);+len=strlen(name);/**NEEDSWORK:Iftheoriginalindexiscrafted,thiscopycould*gounchecked.*/-memcpy(ce->name,ondisk->name,len+1);+memcpy(ce->name,name,len+1);}staticinlinesize_testimate_cache_size(size_tondisk_size,unsignedintentries)
@@ -1415,6 +1428,7 @@ static int ce_write_entry(SHA_CTX *c, int fd, struct cache_entry *ce){intsize=ondisk_ce_size(ce);structondisk_cache_entry*ondisk=xcalloc(1,size);+char*name;ondisk->ctime.sec=htonl(ce->ce_ctime);ondisk->ctime.nsec=0;
@@ -1428,7 +1442,15 @@ static int ce_write_entry(SHA_CTX *c, int fd, struct cache_entry *ce)ondisk->size=htonl(ce->ce_size);hashcpy(ondisk->sha1,ce->sha1);ondisk->flags=htons(ce->ce_flags);-memcpy(ondisk->name,ce->name,ce_namelen(ce));+if(ce->ce_flags&CE_EXTENDED){+structondisk_cache_entry_extended*ondisk2;+ondisk2=(structondisk_cache_entry_extended*)ondisk;+ondisk2->flags2=htons((ce->ce_flags&CE_EXTENDED_FLAGS)>>16);+name=ondisk2->name;+}+else+name=ondisk->name;+memcpy(name,ce->name,ce_namelen(ce));returnce_write(c,fd,ondisk,size);}
@@ -1437,16 +1459,25 @@ int write_index(const struct index_state *istate, int newfd){SHA_CTXc;structcache_headerhdr;-inti,err,removed;+inti,err,removed,extended;structcache_entry**cache=istate->cache;intentries=istate->cache_nr;-for(i=removed=0;i<entries;i++)+for(i=removed=extended=0;i<entries;i++){if(cache[i]->ce_flags&CE_REMOVE)removed++;+/* reduce extended entries if possible */+cache[i]->ce_flags&=~CE_EXTENDED;+if(cache[i]->ce_flags&CE_EXTENDED_FLAGS){+extended++;+cache[i]->ce_flags|=CE_EXTENDED;+}+}+hdr.hdr_signature=htonl(CACHE_SIGNATURE);-hdr.hdr_version=htonl(2);+/* for extended format, increase version so older git won't try to read it */+hdr.hdr_version=htonl(extended?3:2);hdr.hdr_entries=htonl(entries-removed);SHA1_Init(&c);
This bit is the basis of sparse checkout. If this bit is on, the entry
is outside sparse checkout and therefore should be ignored (similar
to CE_VALID)
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
Documentation/git-checkout.txt | 33 +++++++++++++++++++++++++++++++++
cache.h | 10 +++++++++-
read-cache.c | 6 +++---
3 files changed, 45 insertions(+), 4 deletions(-)
@@ -171,6 +171,39 @@ the reflog for HEAD where you were, e.g. $ git log -g -2 HEAD ------------+Sparse checkout+---------------++Normally when you checkout a branch, your working directory+will be fully populated. In some situations, you just need to+work on certain files, no full checkout is needed. Sparse+checkout is a mode that limits the checkout area according to your+needs. With sparse checkout, you can work on a single file, a+collection of files, a subdirectory or a collection of separated+subdirectories.++Because sparse checkout uses a new index format, it will be+incompatible with git prior to 1.6.0 regarding worktree operations.+Operations that only need access to the repository itself, such as+clone, push, or pull/fetch from another (normal) repository... should+not be affected by sparse checkout.++In sparse checkout mode, checkout status of every files in your+working directory will be recorded in index. If a file is marked+"no-checkout", it means that file is not needed to be present in+working directory by user or any git command. When a new file is added+to index, it will be marked "checkout" unless sparse patterns are+applied. Unmerged files are always "checkout". When you checkout new+files using "git checkout <file>" they will be automatically marked+"checkout". Other commands such as "git apply" can also checkout new+files if they are needed.++"No-checkout" status is very similar to "assume-unchanged bit"+(see linkgit:git-update-index[1]). The main difference between them+is "assume unchanged" bit just ignores corresponding files in working+directory while sparse checkout goes a bit farther, remove those files+when it is safe to do so.+ EXAMPLES --------
The first option to be introduced is --sparse, which puts ls-files
in "sparse mode". In this mode, cached entries are divided into
- checkout entries: shown by --cached (new behavior with --sparse)
- no-checkout entries: show by --no-checkout (new option)
- orphaned entries: shown by --orphaned (new option)
Orphaned entries are themselves no-checkout ones but for some reasons
still be present in working directory.
While at it, fix "--deleted" running out of checkout area.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
Documentation/git-ls-files.txt | 24 +++++++++++++++++++++-
builtin-ls-files.c | 41 ++++++++++++++++++++++++++++++++++++---
2 files changed, 59 insertions(+), 6 deletions(-)
@@ -32,7 +33,9 @@ OPTIONS ------- -c:: --cached::- Show cached files in the output (default)+ Show cached files in the output (default). When used with --sparse,+ show only cached files that are marked "checkout", no-checkout+ entries will be excluded. -d:: --deleted::
@@ -72,6 +75,21 @@ OPTIONS to file/directory conflicts for checkout-index to succeed.+--no-checkout::+ Show no-checkout entries. This option implies --sparse.++--orphaned::+ Show orphaned entries. Orphaned entries are no-checkout+ entries that are present in working directory. This option+ implies --sparse.++--sparse::+ When --sparse is passed, cached files will be divided into two+ parts: checkout entries and no-checkout entries.+ --cached will only show checkout entries.+ No-checkout entries can be shown using --orphaned or+ --no-checkout (or both).+ -z:: \0 line termination on output.
@@ -107,6 +125,8 @@ OPTIONS Identify the file status with the following tags (followed by a space) at the start of each line: H:: cached+ -:: no-checkout entries+ O:: orphaned entries M:: unmerged R:: removed/deleted C:: modified/changed
@@ -593,7 +626,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)/* With no flags, we default to showing the cached files */if(!(show_stage|show_deleted|show_others|show_unmerged|-show_killed|show_modified))+show_killed|show_modified|show_orphaned|show_no_checkout))show_cached=1;read_cache();
@@ -196,7 +196,8 @@ to index, it will be marked "checkout" unless sparse patterns are applied. Unmerged files are always "checkout". When you checkout new files using "git checkout <file>" they will be automatically marked "checkout". Other commands such as "git apply" can also checkout new-files if they are needed.+files if they are needed. linkgit:git-update-index[1] can be used to+update "checkout/no-checkout" status in index. "No-checkout" status is very similar to "assume-unchanged bit" (see linkgit:git-update-index[1]). The main difference between them
@@ -99,6 +100,18 @@ in the index e.g. when merging in a commit; thus, in case the assumed-untracked file is changed upstream, you will need to handle the situation manually.+--checkout::+--no-checkout::+ When one of these flags is specified, the object name recorded+ for the paths are not updated. Instead, these options+ set and unset the "no-checkout" bit for the paths. This+ bit is used for marking files for sparse checkout. If+ a path is marked "no-checkout", then it should not be+ checked out unless requested by user or needed for a git+ command to function.+ See linkgit:git-checkout[1] for more information about+ sparse checkout.+ -g:: --again:: Runs 'git-update-index' itself on the paths whose index
@@ -276,6 +277,11 @@ static void update_one(const char *path, const char *prefix, int prefix_length)die("Unable to mark file %s",path);gotofree_return;}+if(mark_no_checkout_only){+if(mark_ce_flags(p,CE_NO_CHECKOUT,mark_no_checkout_only==MARK_FLAG))+die("Unable to mark file %s",path);+gotofree_return;+}if(force_remove){if(remove_file_from_cache(p))
@@ -0,0 +1,36 @@+#!/bin/sh+#+# Copyright (c) 2008 Nguyễn Thái Ngọc Duy+#++test_description='git update-index no-checkout bits (a.k.a sparse checkout)'++../test-lib.sh++test_expect_success'setup''+mkdirsub&&+touch12sub/1sub/2&&+gitadd12sub/1sub/2+'++test_expect_success'index is at version 2''+test"$(test-index-version<.git/index)"=2+'++test_expect_success'update-index --no-checkout''+gitupdate-index--no-checkout1sub/1&&+test-z"$(gitls-files--sparse|grep1)"'++test_expect_success'index is at version 3 after having some no-checkout entries''+test"$(test-index-version<.git/index)"=3+'++test_expect_success'update-index --checkout''+gitupdate-index--checkout1sub/1&&+test"$(gitls-files)"="$(gitls-files--sparse)"'++test_expect_success'index version is back to 2 when there is no no-checkout entry''+test"$(test-index-version<.git/index)"=2+'++test_done
@@ -161,7 +161,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)continue;}-if(ce_uptodate(ce))+if(ce_uptodate(ce)||ce_no_checkout(ce))continue;changed=check_removed(ce,&st);
@@ -348,6 +348,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,structrev_info*revs=cbdata->revs;intmatch_missing,cached;+/* if the entry is not checked out, don't examine work tree */+cached=o->index_only||(idx&&ce_no_checkout(idx));/**Backwardcompatibilitywart-"diff-index -m"does*notmean"do not ignore merges",but"match_missing".
@@ -24,7 +24,9 @@ SYNOPSIS DESCRIPTION ----------- Look for specified patterns in the working tree files, blobs-registered in the index file, or given tree objects.+registered in the index file, or given tree objects. By default+it will search in the working tree files. When in sparse checkout+mode, it only searches checked-out files. OPTIONS
With this you can just do "git checkout some-files" to
widen your checkout. One caveat though: caller must save
the index.
For all of its callers (unpack_trees(), checkout-index, checkout
and apply), only "git apply" does not write index back.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
entry.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
@@ -205,6 +205,51 @@ is "assume unchanged" bit just ignores corresponding files in working directory while sparse checkout goes a bit farther, remove those files when it is safe to do so.+Sparse patterns+---------------++Sparse patterns specify how do you want to form your checkout area.+Many patterns can be specified on one line, separated by colons.+The patterns specify what files should or should not be checked out+on working directory (depends on the option used with the patterns).+Patterns have the following format:++ - An optional prefix '!' which negates the pattern; any+ matching file by a previous pattern will become+ unmatched again. If a negated pattern matches, this will+ override lower precedence patterns sources.++ - If the pattern ends with a slash, it is removed for the+ purpose of the following description, but it would only find+ a match with a directory. In other words, `foo/` will match a+ directory `foo` and paths underneath it, but will not match a+ regular file or a symbolic link `foo` (this is consistent+ with the way how pathspec works in general in git).++ - If the pattern does not contain a slash '/', git treats it as+ a shell glob pattern and checks for a match against the+ pathname without leading directories.++ - Otherwise, git treats the pattern as a shell glob suitable+ for consumption by fnmatch(3) with the FNM_PATHNAME flag:+ wildcards in the pattern will not match a / in the pathname.+ For example, "Documentation/\*.html" matches+ "Documentation/git.html" but not+ "Documentation/ppc/ppc.html". A leading slash matches the+ beginning of the pathname; for example, "/*.c" matches+ "cat-file.c" but not "mozilla-sha1/sha1.c".++ - Patterns begin with a slash will match against full pathname,+ as opposed to normal case when it only matches pathnames relative+ to current working directory.++ - Patterns begin with "./" are treated like normal patterns. That is+ it will follow above rules. But since it has a slash inside,+ "fnmatch rule" will apply. This is a work-around when you do not+ want to apply "no slash" rule.++ - Because colons are used to separate patterns, you cannot put them+ in patterns directly. You must quote them using backslash. EXAMPLES --------
@@ -90,6 +90,12 @@ OPTIONS No-checkout entries can be shown using --orphaned or --no-checkout (or both).+--narrow-match=<sparse patterns>::+ This option can be used to test sparse patterns. The given sparse patterns will+ be used to filter ls-files output. Entries not matching the spec will be+ ignored. This option can only be used with --cached or --stage.+ See linkgit:git-checkout[1] for more information about sparse patterns.+ -z:: \0 line termination on output.
@@ -629,8 +638,14 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)show_killed|show_modified|show_orphaned|show_no_checkout))show_cached=1;+if(narrow_spec&&!show_cached&&!show_stage)+die("ls-files: --narrow-match can only be used with either --cached or --stage");++if(narrow_spec&&narrow_spec->has_root&&prefix_offset!=0)+die("ls-files: --narrow-match with root matching patterns requires --full-name");+read_cache();-if(prefix)+if(prefix&&(!narrow_spec||!narrow_spec->has_root))prune_cache(prefix);if(with_tree){/*
@@ -0,0 +1,39 @@+#!/bin/sh++test_description='This test is for narrow spec matching'++.test-lib.sh++D="$(cd..;pwd)"/t3003++test_pattern(){+test_expect_success"pattern $1"'+(+if[-n"'$3'"];thencd'$3';fi+gitls-files--full-name--narrow-match="'"$2"'">result&&+diff-uresult"'"$D/$1"'"+)+'+}++test_expect_success'setup''+touch123"1:2"&&+mkdir-psub/subsub&&+touchsub/1sub/2sub/3&&+touchsub/subsub/1sub/subsub/2sub/subsub/3&&+gitadd.+'++test_pattern11+test_patternsubsub+test_patternsub-11sub+test_patternroot-sub-1/1sub+test_patternsubsub-slashsubsub/sub+test_patternsub-only'sub/:!sub/subsub/'+test_pattern121:2+test_patterncur-12./1:./2+test_patternslash-1'sub/*1'+test_patternclone-escape'1\:2:1'++test_done+
@@ -726,6 +726,142 @@ static void show_stage_entry(FILE *o,}#endif+structnarrow_spec*parse_narrow_spec(constchar*spec,constchar*prefix)+{+structnarrow_spec*ns;+structnarrow_pattern*p;+constchar*start=spec,*end;+inthas_wildcards,has_slashes;++ns=xmalloc(sizeof(*ns));+memset(ns,0,sizeof(*ns));+if(prefix)+ns->prefix=xstrdup(prefix);++while(*start){+end=start;+has_slashes=has_wildcards=0;+while(*end&&*end!=':'){+if(*end=='*'||*end=='['||*end=='?')+has_wildcards=1;+if(*end=='/')+has_slashes=1;+if(*end=='\\'){+end++;+has_wildcards=1;+if(*end=='\0')/* trailing backslash */+break;+}+end++;+}+if(start==end)+continue;++p=xmalloc(offsetof(structnarrow_pattern,pattern)+(end-start)+1);+p->negative=*start=='!';+if(p->negative)+start++;+p->has_slashes=has_slashes;+p->has_wildcards=has_wildcards;+p->has_trailing_slash=end[-1]=='/';+p->has_root=*start=='/';+if(p->has_root)+start++;+elseif(*start=='.'&&start[1]=='/')+start+=2;+p->len=end-start;+memcpy(p->pattern,start,p->len);+p->pattern[p->len]='\0';++ALLOC_GROW(ns->patterns,ns->nr+1,ns->alloc);+ns->patterns[ns->nr++]=p;+ns->has_root|=p->has_root;++if(*end!=':')+break;+start=end+1;+}+returnns;+}++intmatch_narrow_spec(structnarrow_spec*spec,constchar*path)+{+inti,prefix_len=0;++if(!spec||!spec->nr)+return1;/* always match if spec is NULL */++if(spec->prefix){+/*+*optimization:+*ifthereisnopatternwithleadingslash+*thenitissafetoonlymatchinsideprefix+*/+if(!spec->has_root&&prefixcmp(path,spec->prefix))+return0;+prefix_len=strlen(spec->prefix);+}++for(i=spec->nr-1;i>=0;i--){+structnarrow_pattern*p=spec->patterns[i];+constchar*new_path=path+prefix_len;+intmatch;++if(p->has_root)+new_path=path;/* match full path */+elseif(spec->has_root){+if(prefixcmp(path,spec->prefix))+continue;+}+/* !spec->has_root case has been handled above */++if(p->has_trailing_slash){+/* the only "wildcard" here is backslash escape */+if(p->has_wildcards){+char*unescaped_pattern=xstrdup(p->pattern);+char*src,*dst;++src=dst=unescaped_pattern;+while(*src){+if(*src=='\\')+src++;+if(src!=dst)+*dst=*src;+src++;+dst++;+}+*dst='\0';+match=prefixcmp(new_path,unescaped_pattern)==0;+free(unescaped_pattern);+}+else+match=prefixcmp(new_path,p->pattern)==0;+}+elseif(p->has_slashes){+if(p->has_wildcards)+match=fnmatch(p->pattern,new_path,FNM_PATHNAME)==0;+else+match=strcmp(p->pattern,new_path)==0;+}+else{+constchar*basename=strrchr(path+prefix_len,'/');+if(basename)+basename++;+else+basename=path+prefix_len;+if(p->has_wildcards)+match=fnmatch(p->pattern,basename,0)==0;+else+match=strcmp(p->pattern,basename)==0;+}+if(match)+returnp->negative?0:1;+}++/* no pattern is matched */+return0;+}+intthreeway_merge(structcache_entry**stages,structunpack_trees_options*o){structcache_entry*index;
@@ -94,6 +95,13 @@ then the cloned repository will become corrupt. -n:: No checkout of HEAD is performed after the clone is complete.+--narrow-path=<sparse patterns>::+ Make a sparse checkout instead of full one. The checkout area+ will be narrowed to specific areas based on given sparse+ patterns. This option will not work with either --no-checkout+ or --bare. Please refer to linkgit:git-checkout[1] for more+ detail on sparse checkout and sparse patterns.+ --bare:: Make a 'bare' GIT repository. That is, instead of creating `<directory>` and placing the administrative
@@ -43,6 +44,8 @@ static struct option builtin_clone_options[] = {OPT__QUIET(&option_quiet),OPT_BOOLEAN('n',"no-checkout",&option_no_checkout,"don't create a checkout"),+OPT_STRING(0,"narrow-path",&option_narrow_path,"prefixes",+"limit checkout to specified areas (sparse checkout)"),OPT_BOOLEAN(0,"bare",&option_bare,"create a bare repository"),OPT_BOOLEAN(0,"naked",&option_bare,"create a bare repository"),OPT_BOOLEAN(0,"mirror",&option_mirror,
@@ -378,10 +381,15 @@ int cmd_clone(int argc, const char **argv, const char *prefix)if(option_origin)die("--bare and --origin %s options are incompatible.",option_origin);+if(option_narrow_path)+die("--bare and --narrow-path options are incompatible.");option_no_checkout=1;use_separate_remote=0;}+if(option_no_checkout&&option_narrow_path)+die("--no-checkout and --narrow-path options are incompatible.");+if(!option_origin)option_origin="origin";
@@ -0,0 +1,39 @@+#!/bin/sh++test_description='narrow clone'++../test-lib.sh++test_expect_successsetup'+rm-fr.git&&+test_create_reposrc&&+(+cdsrc+mkdir-pwork/sub/dir+touchuntrackedtrackedmodifiedadded+touchwork/untrackedwork/trackedwork/modifiedwork/added+gitaddtrackedwork/tracked+gitaddmodifiedwork/modified+gitcommit-minitial+)++'++test_expect_success'narrow clone incompatible with --bare''+rm-frdst&&+test_must_failgitclone--narrow-path=work--baresrcdst+'++test_expect_success'narrow clone incompatible with --no-checkout''+rm-frdst&&+test_must_failgitclone--narrow-path=work-nsrcdst+'++test_expect_success'clone with --narrow-path''+rm-frdst&&+gitclone--narrow-path=worksrcdst&&+cddst&&+test-z"$(gitls-files--sparse|grep-v^work/)"+'++test_done
This patch teaches unpack_trees() to checkout/remove entries
on working directories appropriately when sparse checkout area is
changed. There are three kind of changes:
- new_narrow_path: reset workdir to a completely new checkout area
- add_narrow_path: keep current areas and add more entries
- remove_narrow_path: remove some entries from current areas
CE_WD_REMOVE is introduced to remove entries from working directories,
but still keep them in index
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
cache.h | 3 ++
unpack-trees.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
unpack-trees.h | 4 +++
3 files changed, 80 insertions(+), 1 deletions(-)
@@ -167,6 +167,9 @@ struct cache_entry {#define CE_HASHED (0x100000)#define CE_UNHASHED (0x200000)+/* Only remove in work directory, not index */+#define CE_WD_REMOVE (0x400000)+/**Extendedon-diskflags*/
@@ -96,7 +96,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_WD_REMOVE))total++;}
@@ -108,6 +108,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_WD_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)
@@ -133,6 +140,66 @@ static int check_updates(struct unpack_trees_options *o)returnerrs!=0;}+staticintverify_uptodate(structcache_entry*ce,structunpack_trees_options*o);+staticintapply_narrow_spec(structunpack_trees_options*o)+{+structindex_state*index=&o->result;+inti;++if(!(o->new_narrow_path|o->add_narrow_path|o->remove_narrow_path))+return0;++for(i=0;i<index->cache_nr;i++){+structcache_entry*ce=index->cache[i];+intwas_checkout=ce_checkout(ce);+intmatch=match_narrow_spec(o->narrow_spec,ce->name);++if(ce_stage(ce))+continue;++if(o->new_narrow_path){+if(match)+ce_mark_checkout(ce);+else+ce_mark_no_checkout(ce);+}++if(o->add_narrow_path&&match)+ce_mark_checkout(ce);++if(o->remove_narrow_path&&match)+ce_mark_no_checkout(ce);++/* Update worktree, add/remove entries if needed */++/*+*Weonlycareaboutfilesgettingintothecheckoutarea+*Ifmergestrategieswanttoremovesome,goahead+*/+if(ce->ce_flags&CE_REMOVE)+continue;++if(was_checkout&&ce_no_checkout(ce)){+/*+*IfCE_UPDATEisset,verify_uptodate()mustbecalledalready+*alsostatinfomayhavelostaftermerged_entry()socalling+*verify_uptodate()againmayfail+*/+if(!(ce->ce_flags&CE_UPDATE)&&verify_uptodate(ce,o))+return-1;+ce->ce_flags|=CE_WD_REMOVE;+}+if(!was_checkout&&ce_checkout(ce))+ce->ce_flags|=CE_UPDATE;++/* merge strategies may set CE_UPDATE outside checkout area */+if(ce_no_checkout(ce))+ce->ce_flags&=~CE_UPDATE;++}+return0;+}+staticinlineintcall_unpack_fn(structcache_entry**src,structunpack_trees_options*o){intret=o->fn(src,o);
This patch adds main interface to manipulate sparse checkout.
New options are added to support entering/updating/leaving sparse
checkout:
--full: return to full checkout (default)
--reset-path: set checkout area according to given spec
--add-path/--remove-path: adjust current sparse checkout area
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
Documentation/git-checkout.txt | 54 +++++++++++++++++++-
builtin-checkout.c | 37 ++++++++++++++
t/t2011-checkout-sparse.sh | 108 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 196 insertions(+), 3 deletions(-)
create mode 100755 t/t2011-checkout-sparse.sh
@@ -8,8 +8,10 @@ git-checkout - Checkout a branch or paths to the working tree SYNOPSIS -------- [verse]-'git checkout' [-q] [-f] [--track | --no-track] [-b <new_branch> [-l]] [-m] [<branch>]-'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...+'git checkout' [-q] [-f] [--track | --no-track] [-b <new_branch> [-l]] [-m]+ [<sparse checkout options>] [<branch>]+'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>]+ [<sparse checkout options>] [--] <paths>... DESCRIPTION -----------
@@ -34,6 +36,10 @@ used to specify a specific tree-ish (i.e. commit, tag or tree) to update the index for the given paths before updating the working tree.+<sparse checkout options> include --full, --reset-path, --add-path+and --remove-path. The last three require sparse patterns. Please refer+to "sparse checkout" section for more information about this mode.+ The index may contain unmerged entries after a failed merge. By default, if you try to check out such an entry from the index, the checkout operation will fail and nothing will be checked out.
@@ -117,6 +123,32 @@ should result in deletion of the path). When checking out paths from the index, this option lets you recreate the conflicted merge in the specified paths.+--full::+ Quit sparse checkout mode. Return to full checkout. This option+ cannot be used with either --reset-path, --add-path,+ --remove-path or <paths>.++--reset-path=<sparse patterns>::+ Re-apply new sparse patterns on current working directory to+ form new checkout area. All no-checkout bits will be wiped+ out before applying the patterns. This option cannot be used+ with --full, --add-path, --remove-path or <paths>. Multiple+ --reset-path is not allowed.++--add-path=<sparse patterns>::+ Checkout more areas specified by sparse patterns to current+ checkout area. Already checked out entries are not affected.+ This option cannot be used with --full, --reset-path,+ --remove-path or <paths>. Multiple --add-path is not allowed.++--remove-path=<sparse patterns>::+ Narrow checkout area by removing files specified by sparse patterns+ from current checkout area. This operation will fail if there+ are unmerged or modified files in the removing areas. No-checkout+ entries are not affected. This option cannot be used with --full,+ --reset-path, --add-path or <paths>. Multiple --remove-path is not+ allowed.+ --conflict=<style>:: The same as --merge option above, but changes the way the conflicting hunks are presented, overriding the
@@ -186,7 +218,10 @@ Because sparse checkout uses a new index format, it will be incompatible with git prior to 1.6.0 regarding worktree operations. Operations that only need access to the repository itself, such as clone, push, or pull/fetch from another (normal) repository... should-not be affected by sparse checkout.+not be affected by sparse checkout. In order to make your working+directory work again with those versions, you can use+`git checkout --full` to return to normal mode (and compatible index+format). In sparse checkout mode, checkout status of every files in your working directory will be recorded in index. If a file is marked
@@ -251,6 +286,19 @@ Patterns have the following format: - Because colons are used to separate patterns, you cannot put them in patterns directly. You must quote them using backslash.+When you apply new sparse patterns to your working directory using either+--reset-path, --add-path or --remove-path, it will update "checkout" status+in index accordingly. Moreover, if a file is marked "no-checkout" and+is present in working directory, it will be removed. If a file is+turned from "no-checkout" to "checkout", then it will be added again+to working directory. Modified and unmerged entries can't bear+"no-checkout" status, if sparse patterns apply to them, "git checkout"+will refuse to update working directory.++Sparse patterns are not saved by "git checkout" anywhere in the repository.+You can form your checkout area in one go with --reset-path option,+or do it incrementally with --add-path and --remove-path.+ EXAMPLES --------
@@ -639,6 +667,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)if(!opts.new_branch&&(opts.track!=git_branch_track))die("git checkout: --track and --no-track require -b");+if(((opts.all_path?1:0)++(opts.new_path?1:0)++(opts.add_path?1:0)++(opts.remove_path?1:0))>1)+die("git checkout: --reset-path, --full, --add-path and --remove-path are incompatible");+if(opts.force&&opts.merge)die("git checkout: -f and -m are incompatible");
@@ -732,6 +766,9 @@ no_reference:if(1<!!opts.writeout_stage+!!opts.force+!!opts.merge)die("git checkout: --ours/--theirs, --force and --merge are incompatible when\nchecking out of the index.");+if(opts.all_path||opts.new_path||opts.add_path||opts.remove_path)+die("git checkout: updating paths is incompatible with setting sparse checkout");+returncheckout_paths(source_tree,pathspec,&opts);}
@@ -0,0 +1,108 @@+#!/bin/sh++test_description='sparse checkout'++../test-lib.sh++test_expect_successsetup'+mkdirwork1work2work3+touchonetwothree+touchwork1/onework2/twowork3/three+gitaddonework1/one+gitcommit-mwork1+gitaddtwowork2/two+gitcommit-mwork2+gitaddthreework3/three+gitcommit-mwork3+'++test_expect_success'--full on no-narrow checkout''+gitcheckout--full+'++test_expect_success'--full and --reset-path incompatible''+test_must_failgitcheckout--full--reset-path=work1+'++test_expect_success'limit worktree to work1 and work2''+gitcheckout--reset-path=work1/:work2/&&+test-fwork1/one&&+test-fwork2/two&&+!test-fwork3/three+'++test_expect_success'update worktree to work2 and work3''+gitcheckout--reset-path=work2/:work3/&&+!test-fwork1/one&&+test-fwork2/two&&+test-fwork3/three+'++test_expect_success'update narrow prefix with modification''+echomodified>>work2/two&&+gitcheckout--reset-path=work1/:work2/&&+test-fwork1/one&&+test-fwork2/two&&+!test-fwork3/three&&+grep-qmodifiedwork2/two+'++test_expect_success'update checkout should not lose modification''+!gitcheckout--reset-path=work1/:work3/&&+test-fwork1/one&&+test-fwork2/two&&+!test-fwork3/three&&+grep-qmodifiedwork2/two+'++test_expect_success'widen checkout area''+gitcheckout--add-path=work3/&&+test-fwork1/one&&+test-fwork2/two&&+test-fwork3/three+'++test_expect_success'narrow checkout area''+gitcheckout--remove-path=work3/&&+test-fwork1/one&&+test-fwork2/two&&+!test-fwork3/three+'++test_expect_success'update outside checkout area''+echoone>>work1/one&&+gitaddwork1/one&&+gitcommit-mupdate&&+gitcheckout--reset-path=work2/&&+gitcheckoutHEAD^&&+gitcheckoutmaster+'++test_expect_success'conflict outside checkout area''+gitcheckout--add-path=work1/one-bconflictHEAD~2&&+echotwo>>work1/one&&+gitaddwork1/one&&+gitcommit-mconflict-update&&+gitcheckout--reset-path=work2/master&&+test-z"$(gitls-files--sparsework1/one)"+gitmergeconflict+test$?=1&&+test-n"$(gitls-files--sparsework1/one)"&&+gitreset--hardHEAD+'++test_expect_success'removal outside checkout area''+gitrmwork1/one&&+gitcommit-mremove&&+gitcheckout--reset-path=work2/HEAD^+'++test_expect_success'exit sparse checkout''+gitcheckout--full&&+test-fwork1/one&&+test-fwork2/two&&+test-fwork3/three&&+testone+'++test_done
@@ -20,6 +20,7 @@ static char wt_status_colors[][COLOR_MAXLEN] = {"\033[31m",/* WT_STATUS_CHANGED: red */"\033[31m",/* WT_STATUS_UNTRACKED: red */"\033[31m",/* WT_STATUS_NOBRANCH: red */+"\033[31m",/* WT_STATUS_ORPHANED: red */};enumuntracked_status_typeshow_untracked_files=SHOW_NORMAL_UNTRACKED_FILES;
@@ -83,6 +84,16 @@ static void wt_status_print_dirty_header(struct wt_status *s,color_fprintf_ln(s->fp,c,"#");}+staticvoidwt_status_print_orphaned_header(structwt_status*s)+{+constchar*c=color(WT_STATUS_HEADER);+color_fprintf_ln(s->fp,c,"# Orphaned files:");+color_fprintf_ln(s->fp,c,"# (these are tracked, but marked no-checkout and should not be present)");+color_fprintf_ln(s->fp,c,"# (use \"git update-index --checkout\" to remove no-checkout status)");+color_fprintf_ln(s->fp,c,"# (otherwise remove them to avoid confusion because git will ignore them)");+color_fprintf_ln(s->fp,c,"#");+}+staticvoidwt_status_print_untracked_header(structwt_status*s){constchar*c=color(WT_STATUS_HEADER);
On Sat, Sep 20, 2008 at 12:01 PM, Nguyễn Thái Ngọc Duy
[off-list ref] wrote:
Nguyễn Thái Ngọc Duy (14):
Extend index to save more flags
Introduce CE_NO_CHECKOUT bit
ls-files: add options to support sparse checkout
update-index: refactor mark_valid() in preparation for new options
update-index: add --checkout/--no-checkout to update CE_NO_CHECKOUT bit
ls-files: Add tests for --sparse and friends
Prevent diff machinery from examining worktree outside sparse checkout
checkout_entry(): CE_NO_CHECKOUT on checked out entries.
grep: skip files outside sparse checkout area
ls-files: support "sparse patterns", used to form sparse checkout areas
unpack_trees(): add support for sparse checkout
clone: support sparse checkout with --narrow-path option
checkout: add new options to support sparse checkout
wt-status: Show orphaned entries in "git status" output
I would like to test it, do you have a public repo to fetch it?
Santi
On Sat, Sep 20, 2008 at 12:01 PM, Nguyễn Thái Ngọc Duy
[off-list ref] wrote:
>
> Nguyễn Thái Ngọc Duy (14):
> Extend index to save more flags
> Introduce CE_NO_CHECKOUT bit
> ls-files: add options to support sparse checkout
> update-index: refactor mark_valid() in preparation for new options
> update-index: add --checkout/--no-checkout to update CE_NO_CHECKOUT bit
> ls-files: Add tests for --sparse and friends
> Prevent diff machinery from examining worktree outside sparse checkout
> checkout_entry(): CE_NO_CHECKOUT on checked out entries.
> grep: skip files outside sparse checkout area
> ls-files: support "sparse patterns", used to form sparse checkout areas
> unpack_trees(): add support for sparse checkout
> clone: support sparse checkout with --narrow-path option
> checkout: add new options to support sparse checkout
> wt-status: Show orphaned entries in "git status" output
>
I would like to test it, do you have a public repo to fetch it?
I am not sure about that change, especially the fact that git-clone
and git-checkout use differently named options, because those options
affect clone only as they affect the checkout part of the clone. One
would think that git-clone = git-init + git-remote add + git-fetch +
git-checkout, and that git-clone would simply pass sparse checkout
flags to git-checkout.
- New narrow spec (or "sparse patterns" from now) resembles
.gitignore patterns
You mean here that rules for patterns to select which parts of tree
mark as "no-checkout" and/or checkout/leave in checkout are the same
(or nearly the same) as rules for ignoring files, isn't it?
BTW I think that the same rules are used in gitattributes, aren't
they?
- "git ls-files" now supports more fine-grained listing. It can now
list checkout files, no-checkout files or orphaned (previously
"overlay") files. --overlay is gone
Good. I hope (I haven't read the post yet) that you extended '-t' and
'-v' output (or added similar option for no-checkout bit specially)
for git-ls-files.
- "git status" shows orphaned entries and remedies
Good. I guess (I haven't read the post yet) that git-status displays,
or can be asked to display "orphaned"/"unwanted" files (files which
exists in working repository, but are marked with "no-checkout" bit),
and perhaps simply the fact that we commit/are in narrow checkout
(there is at least one file with "no-checkout" bit set in the index).
For code changes, significant changes are:
[10/14] ls-files: support "sparse patterns", used to form sparse
checkout areas
Hmmm...
I hope I have addressed all the issues. If I miss anything, please
speak up.
By the way, pleas do not worry if there would be new round of
comments. Sparse checkout is a new feature, and I think it is quite
important to get UI (interface) part, like names of configuration
variables and options first, or at least correct them before sparse
checkout hits released version. It is harder IMVHO to change user
interface (this applies also to non-local repository data) due to
concerns for backwards compatibility; it is I think easier to correct
code.
Nguyá»
n Thái Ngá»c Duy (14):
Errr... what happened here? For me it doesn't look like correct UTF-8
encoding, but perhaps that it is just my news client (Gnus)...
P.S. Thanks for numbering this series.
--
Jakub Narebski
Poland
ShadeHawk on #git
> - "git clone --path" => "git clone --narrow-path"
> - "git checkout --path" => "git checkout --reset-path"
I am not sure about that change, especially the fact that git-clone
and git-checkout use differently named options, because those options
affect clone only as they affect the checkout part of the clone. One
would think that git-clone = git-init + git-remote add + git-fetch +
git-checkout, and that git-clone would simply pass sparse checkout
flags to git-checkout.
Johannes sixt said --path was too generic so I changed the name. Hmm..
I did not think the same option name for git-checkout and git-clone
was important, rather worry about people may misunderstand that it is
"narrow clone" (do not fetch objects outside given paths for all
history). Maybe "git clone --narrow-checkout" would be better.
"--reset-path", I think, is a better name though. It would express the
relation compared to --add-path and --remove-path.
> - New narrow spec (or "sparse patterns" from now) resembles
> .gitignore patterns
You mean here that rules for patterns to select which parts of tree
mark as "no-checkout" and/or checkout/leave in checkout are the same
(or nearly the same) as rules for ignoring files, isn't it?
Yes, almost the same, exceptions include "./" support (this may have
worked already for .gitignore, I dunno) and backslash escape for
colons.
BTW I think that the same rules are used in gitattributes, aren't
they?
They have different implementations. Though the rules may be the same.
> Nguyễn Thái NgỠc Duy (14):
Errr... what happened here? For me it doesn't look like correct UTF-8
encoding, but perhaps that it is just my news client (Gnus)...
The cover letter lacks MIME-Version and Content-Type, hmm..
--
Duy
I am not sure about that change, especially the fact that git-clone
and git-checkout use differently named options, because those options
affect clone only as they affect the checkout part of the clone. One
would think that git-clone = git-init + git-remote add + git-fetch +
git-checkout, and that git-clone would simply pass sparse checkout
flags to git-checkout.
Johannes sixt said --path was too generic so I changed the name. Hmm..
I did not think the same option name for git-checkout and git-clone
was important, rather worry about people may misunderstand that it is
"narrow clone" (do not fetch objects outside given paths for all
history). Maybe "git clone --narrow-checkout" would be better.
True, I didn't thought that git-clone can have option with explicit
'checkout' in a name, for example --checkout-paths, or --checkout-only,
or --narrow-checkout (although for me this one doesn't look as it
accepts arguments, at least on first glance), or --sparse-checkout
(the same).
"--reset-path", I think, is a better name though. It would express the
relation compared to --add-path and --remove-path.
I don't like very much '--reset-path' option name, because it is not
about 'reset' or 'resetting', but about limiting checkout to specified
paths. Unfortunately --include / --exclude looks like are for ignoring
files, not marking files with "no-checkout" bit etc.
But I am not native English speaker.
Further proposals: --only ("git checkout --only <pattern>") with
--checkout-only as counterpart in git-clone; --limit-to, --sparse.
GNU tar uses --exclude and --exclude-file (with --no-recurse,
--no-wildcards, --no-wildcards-match-slash). wget uses --accept
and --reject for filename patterns, and --include / --exclude for
directories. Neither looks right for sparse checkout in Git.
quoted
quoted
- New narrow spec (or "sparse patterns" from now) resembles
.gitignore patterns
You mean here that rules for patterns to select which parts of tree
mark as "no-checkout" and/or checkout/leave in checkout are the same
(or nearly the same) as rules for ignoring files, isn't it?
Yes, almost the same, exceptions include "./" support (this may have
worked already for .gitignore, I dunno) and backslash escape for
colons.
'./', or rather '/' support works for gitignore: this is the only way
to have pattern which matches only files in given directory,
nonrecursively. For example last line in last example on gitignore(5)
man page.
quoted
BTW I think that the same rules are used in gitattributes, aren't
they?
They have different implementations. Though the rules may be the same.
Were you able to reuse either one?
quoted
quoted
Nguyễn Thái NgỠc Duy (14):
Errr... what happened here? For me it doesn't look like correct UTF-8
encoding, but perhaps that it is just my news client (Gnus)...
The cover letter lacks MIME-Version and Content-Type, hmm..
Bug in git-format-patch? IIRC --cover-letter was added quite late, and
is quite a new option; some bugs might have been not ironed out yet.
--
Jakub Narebski
Poland
Hello,
On Sat, Sep 20, 2008 at 08:01:27PM +0200, Jakub Narebski wrote:
On Sat, 20 Sep 2008, Nguyen Thai Ngoc Duy wrote:
quoted
quoted
quoted
Nguyễn Thái NgỠc Duy (14):
Errr... what happened here? For me it doesn't look like correct UTF-8
encoding, but perhaps that it is just my news client (Gnus)...
The cover letter lacks MIME-Version and Content-Type, hmm..
Bug in git-format-patch? IIRC --cover-letter was added quite late, and
is quite a new option; some bugs might have been not ironed out yet.
I hit this kind of problem already, too.
My problem was that format-patch only adds MIME-Version and
Content-Type headers if the commit has non-ascii characters. If I add a
S-o-b only after the format-patch step I easily forget to add the needed
headers. IMHO the right fix is to let send-email stop if there is no
encoding related header in the mail but non-ascii characters.
Best regards
Uwe
> "--reset-path", I think, is a better name though. It would express the
> relation compared to --add-path and --remove-path.
I don't like very much '--reset-path' option name, because it is not
about 'reset' or 'resetting', but about limiting checkout to specified
paths. Unfortunately --include / --exclude looks like are for ignoring
files, not marking files with "no-checkout" bit etc.
But I am not native English speaker.
Further proposals: --only ("git checkout --only <pattern>") with
--checkout-only as counterpart in git-clone; --limit-to, --sparse.
GNU tar uses --exclude and --exclude-file (with --no-recurse,
--no-wildcards, --no-wildcards-match-slash). wget uses --accept
and --reject for filename patterns, and --include / --exclude for
directories. Neither looks right for sparse checkout in Git.
I think --exclude and --include are quite good. With Junio's
suggestion "foo-X", how about this?
git clone --sparse-checkout=<patterns> [1]
git checkout --set-sparse=<patterns>
git checkout --include-sparse=<patterns>
git checkout --exclude-sparse=<patterns> [2]
[1] "checkout" is there to avoid being interpreted as "sparse clone"
[2] --narrow-sparse IMO does not tell how the following patterns are
used (is it the set that will be excluded or the target set?),
"exclude" does better.
>> BTW I think that the same rules are used in gitattributes, aren't
>> they?
>
> They have different implementations. Though the rules may be the same.
Were you able to reuse either one?
No. .gitignore is tied to read_directory() while .gitattributes has
attributes attached. So I rolled out another one for index.
--
Duy
From: Jakub Narebski <hidden> Date: 2016-06-15 22:45:23
Comments below are just nitpicking. Feel free to diregard them...
Nguyễn Thái Ngọc Duy [off-list ref] writes:
The on-disk format of index only saves 16 bit flags, nearly all have
been used. The last bit (CE_EXTENDED) is used to for future extension.
This patch extends index entry format to save more flags in future.
The new entry format will be used when CE_EXTENDED bit is 1.
Because older implementation may not understand CE_EXTENDED bit and
misread the new format, if there is any extended entry in index, index
header version will turn 3, which makes it incompatible for older git.
If there is none, header version will return to 2 again.
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
It would be nice if at least this part of series got accepted...
@@ -109,6 +109,26 @@ struct ondisk_cache_entry {charname[FLEX_ARRAY];/* more */};+/*+*ThisstructisusedwhenCE_EXTENDEDbitis1+*Thestructmustmatchondisk_cache_entryexactlyfrom+*ctimetillflags+*/
Errr... "must match"? Wouldn't "does match" be better?
This type is defined below, not is to be defined...
+struct ondisk_cache_entry_extended {
+ struct cache_time ctime;
+ struct cache_time mtime;
+ unsigned int dev;
+ unsigned int ino;
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ unsigned char sha1[20];
+ unsigned short flags;
+ unsigned short flags2;
flags and flags2? Why not flags1 and flags2, or flags[2], or flags and
flags_ext/flags_extended?
Just nitpicking.
quoted hunk
+ char name[FLEX_ARRAY]; /* more */
+};
+
struct cache_entry {
unsigned int ce_ctime;
unsigned int ce_mtime;
@@ -130,7 +150,15 @@ struct cache_entry { #define CE_VALID (0x8000) #define CE_STAGESHIFT 12-/* In-memory only */+/*+ * Range 0xFFFF0000 in ce_flags is divided into+ * two parts: in-memory flags and on-disk ones.+ * Flags in CE_EXTENDED_FLAGS will get saved on-disk
Semicolon at the end of below text to separate, I think. Or at least
comma.
+ * if you want to save a new flag, add it in
+ * CE_EXTENDED_FLAGS
+
+#define CE_EXTENDED_FLAGS (0)
+
+/*
+ * Safeguard to avoid saving wrong flags:
+ * - CE_EXTENDED2 won't get saved until its semantic is known
+ * - Bits in 0x0000FFFF have been saved in ce_flags already
+ * - Bits in 0x003F0000 are currently in-memory flags
+ */
+#if CE_EXTENDED_FLAGS & 0x80CFFFFF
+#error "CE_EXTENDED_FLAGS out of range"
+#endif
I don't quite understand the above fragment (especially with the fact
that CE_EXTENDED_FLAGS is defined as (0))...
@@ -1096,7 +1096,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)if(hdr->hdr_signature!=htonl(CACHE_SIGNATURE))returnerror("bad signature");-if(hdr->hdr_version!=htonl(2))+if(hdr->hdr_version!=htonl(2)&&hdr->hdr_version!=htonl(3))returnerror("bad index version");
By the way: what was index version 1?
[...]
--
Jakub Narebski
Poland
ShadeHawk on #git
> +
> +#define CE_EXTENDED_FLAGS (0)
> +
> +/*
> + * Safeguard to avoid saving wrong flags:
> + * - CE_EXTENDED2 won't get saved until its semantic is known
> + * - Bits in 0x0000FFFF have been saved in ce_flags already
> + * - Bits in 0x003F0000 are currently in-memory flags
> + */
> +#if CE_EXTENDED_FLAGS & 0x80CFFFFF
> +#error "CE_EXTENDED_FLAGS out of range"
> +#endif
I don't quite understand the above fragment (especially with the fact
that CE_EXTENDED_FLAGS is defined as (0))...
Because this patch does not introduce any new on-disk flag yet so
CE_EXTENDED_FLAGS remains 0. In the next patch, CE_EXTENDED_FLAGS will
be updated to have CE_NO_CHECKOUT.
--
Duy
From: Jakub Narebski <hidden> Date: 2016-06-15 22:45:23
On Sun, 21 Sep 2008, Nguyen Thai Ngoc Duy wrote:
On 9/21/08, Jakub Narebski [off-list ref] wrote:
quoted
quoted
+
+#define CE_EXTENDED_FLAGS (0)
+
+/*
+ * Safeguard to avoid saving wrong flags:
+ * - CE_EXTENDED2 won't get saved until its semantic is known
+ * - Bits in 0x0000FFFF have been saved in ce_flags already
+ * - Bits in 0x003F0000 are currently in-memory flags
+ */
+#if CE_EXTENDED_FLAGS & 0x80CFFFFF
+#error "CE_EXTENDED_FLAGS out of range"
+#endif
I don't quite understand the above fragment (especially with the fact
that CE_EXTENDED_FLAGS is defined as (0))...
Because this patch does not introduce any new on-disk flag yet so
CE_EXTENDED_FLAGS remains 0. In the next patch, CE_EXTENDED_FLAGS will
be updated to have CE_NO_CHECKOUT.
Well, now I understand CE_EXTENDED_FLAGS being (0).
What I still don't understand the pattern it is protected against.
As I understand it if CE_EXTENDED_FLAGS & 0x0000FFFF it is bad,
because ce_flags saved flags are not extended flags, and
CE_EXTENDED_FLAGS & 0x003F0000 are in-memory flags. But why
CE_EXTENDED_FLAGS & 0x80C00000 is bad, and why (if I understand it)
CE_EXTENDED_FLAGS & 0x00300000 is not bad.
--
Jakub Narebski
Poland
Hi,
Just some comments.
When you exclude the .gitignore file all the ignored files are
reported as "Untracked files". I.e, as in:
$git clone $git_url
$ cd git
$ make
$ git checkout --reset-path=Documentation/
$ git status
When you have local changes it says that it cannot switch branches
$ git checkout --reset-path=Documentation/
error: You have local changes to 'Makefile'; cannot switch branches.
$ git checkout -h
...
--reset-path <prefixes>
reset to new sparse checkout
--add-path <prefixes>
widen checkout area
--remove-path <prefixes>
narrow checkout area
s/prefixes/sparse patterns/
Best regards,
Santi