mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
Merge branch 'jc/nostat'
* jc/nostat: cache_name_compare() compares name and stage, nothing else. "assume unchanged" git: documentation. ls-files: split "show-valid-bit" into a different option. "Assume unchanged" git: --really-refresh fix. ls-files: debugging aid for CE_VALID changes. "Assume unchanged" git: do not set CE_VALID with --refresh "Assume unchanged" git
This commit is contained in:
commit
ee072260db
|
@ -8,7 +8,8 @@ git-ls-files - Information about files in the index/working directory
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-ls-files' [-z] [-t]
|
[verse]
|
||||||
|
'git-ls-files' [-z] [-t] [-v]
|
||||||
(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])\*
|
(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])\*
|
||||||
(-[c|d|o|i|s|u|k|m])\*
|
(-[c|d|o|i|s|u|k|m])\*
|
||||||
[-x <pattern>|--exclude=<pattern>]
|
[-x <pattern>|--exclude=<pattern>]
|
||||||
|
@ -87,6 +88,10 @@ OPTIONS
|
||||||
K:: to be killed
|
K:: to be killed
|
||||||
?:: other
|
?:: other
|
||||||
|
|
||||||
|
-v::
|
||||||
|
Similar to `-t`, but use lowercase letters for files
|
||||||
|
that are marked as 'always matching index'.
|
||||||
|
|
||||||
--full-name::
|
--full-name::
|
||||||
When run from a subdirectory, the command usually
|
When run from a subdirectory, the command usually
|
||||||
outputs paths relative to the current directory. This
|
outputs paths relative to the current directory. This
|
||||||
|
|
|
@ -8,11 +8,14 @@ git-update-index - Modifies the index or directory cache
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
|
[verse]
|
||||||
'git-update-index'
|
'git-update-index'
|
||||||
[--add] [--remove | --force-remove] [--replace]
|
[--add] [--remove | --force-remove] [--replace]
|
||||||
[--refresh [-q] [--unmerged] [--ignore-missing]]
|
[--refresh [-q] [--unmerged] [--ignore-missing]]
|
||||||
[--cacheinfo <mode> <object> <file>]\*
|
[--cacheinfo <mode> <object> <file>]\*
|
||||||
[--chmod=(+|-)x]
|
[--chmod=(+|-)x]
|
||||||
|
[--assume-unchanged | --no-assume-unchanged]
|
||||||
|
[--really-refresh]
|
||||||
[--info-only] [--index-info]
|
[--info-only] [--index-info]
|
||||||
[-z] [--stdin]
|
[-z] [--stdin]
|
||||||
[--verbose]
|
[--verbose]
|
||||||
|
@ -65,6 +68,18 @@ OPTIONS
|
||||||
--chmod=(+|-)x::
|
--chmod=(+|-)x::
|
||||||
Set the execute permissions on the updated files.
|
Set the execute permissions on the updated files.
|
||||||
|
|
||||||
|
--assume-unchanged, --no-assume-unchanged::
|
||||||
|
When these flags are specified, the object name recorded
|
||||||
|
for the paths are not updated. Instead, these options
|
||||||
|
sets and unsets the "assume unchanged" bit for the
|
||||||
|
paths. When the "assume unchanged" bit is on, git stops
|
||||||
|
checking the working tree files for possible
|
||||||
|
modifications, so you need to manually unset the bit to
|
||||||
|
tell git when you change the working tree file. This is
|
||||||
|
sometimes helpful when working with a big project on a
|
||||||
|
filesystem that has very slow lstat(2) system call
|
||||||
|
(e.g. cifs).
|
||||||
|
|
||||||
--info-only::
|
--info-only::
|
||||||
Do not create objects in the object database for all
|
Do not create objects in the object database for all
|
||||||
<file> arguments that follow this flag; just insert
|
<file> arguments that follow this flag; just insert
|
||||||
|
@ -193,6 +208,37 @@ $ git ls-files -s
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
||||||
|
Using "assume unchanged" bit
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Many operations in git depend on your filesystem to have an
|
||||||
|
efficient `lstat(2)` implementation, so that `st_mtime`
|
||||||
|
information for working tree files can be cheaply checked to see
|
||||||
|
if the file contents have changed from the version recorded in
|
||||||
|
the index file. Unfortunately, some filesystems have
|
||||||
|
inefficient `lstat(2)`. If your filesystem is one of them, you
|
||||||
|
can set "assume unchanged" bit to paths you have not changed to
|
||||||
|
cause git not to do this check. Note that setting this bit on a
|
||||||
|
path does not mean git will check the contents of the file to
|
||||||
|
see if it has changed -- it makes git to omit any checking and
|
||||||
|
assume it has *not* changed. When you make changes to working
|
||||||
|
tree files, you have to explicitly tell git about it by dropping
|
||||||
|
"assume unchanged" bit, either before or after you modify them.
|
||||||
|
|
||||||
|
In order to set "assume unchanged" bit, use `--assume-unchanged`
|
||||||
|
option. To unset, use `--no-assume-unchanged`.
|
||||||
|
|
||||||
|
The command looks at `core.ignorestat` configuration variable. When
|
||||||
|
this is true, paths updated with `git-update-index paths...` and
|
||||||
|
paths updated with other git commands that update both index and
|
||||||
|
working tree (e.g. `git-apply --index`, `git-checkout-index -u`,
|
||||||
|
and `git-read-tree -u`) are automatically marked as "assume
|
||||||
|
unchanged". Note that "assume unchanged" bit is *not* set if
|
||||||
|
`git-update-index --refresh` finds the working tree file matches
|
||||||
|
the index (use `git-update-index --really-refresh` if you want
|
||||||
|
to mark them as "assume unchanged").
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
To update and refresh only the files already checked out:
|
To update and refresh only the files already checked out:
|
||||||
|
@ -201,6 +247,35 @@ To update and refresh only the files already checked out:
|
||||||
$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
|
$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
On an inefficient filesystem with `core.ignorestat` set:
|
||||||
|
|
||||||
|
------------
|
||||||
|
$ git update-index --really-refresh <1>
|
||||||
|
$ git update-index --no-assume-unchanged foo.c <2>
|
||||||
|
$ git diff --name-only <3>
|
||||||
|
$ edit foo.c
|
||||||
|
$ git diff --name-only <4>
|
||||||
|
M foo.c
|
||||||
|
$ git update-index foo.c <5>
|
||||||
|
$ git diff --name-only <6>
|
||||||
|
$ edit foo.c
|
||||||
|
$ git diff --name-only <7>
|
||||||
|
$ git update-index --no-assume-unchanged foo.c <8>
|
||||||
|
$ git diff --name-only <9>
|
||||||
|
M foo.c
|
||||||
|
|
||||||
|
<1> forces lstat(2) to set "assume unchanged" bits for paths
|
||||||
|
that match index.
|
||||||
|
<2> mark the path to be edited.
|
||||||
|
<3> this does lstat(2) and finds index matches the path.
|
||||||
|
<4> this does lstat(2) and finds index does not match the path.
|
||||||
|
<5> registering the new version to index sets "assume unchanged" bit.
|
||||||
|
<6> and it is assumed unchanged.
|
||||||
|
<7> even after you edit it.
|
||||||
|
<8> you can tell about the change after the fact.
|
||||||
|
<9> now it checks with lstat(2) and finds it has been changed.
|
||||||
|
------------
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
@ -213,6 +288,9 @@ in the index and the file mode on the filesystem if they differ only on
|
||||||
executable bit. On such an unfortunate filesystem, you may
|
executable bit. On such an unfortunate filesystem, you may
|
||||||
need to use `git-update-index --chmod=`.
|
need to use `git-update-index --chmod=`.
|
||||||
|
|
||||||
|
The command looks at `core.ignorestat` configuration variable. See
|
||||||
|
'Using "assume unchanged" bit' section above.
|
||||||
|
|
||||||
|
|
||||||
See Also
|
See Also
|
||||||
--------
|
--------
|
||||||
|
|
2
apply.c
2
apply.c
|
@ -1317,7 +1317,7 @@ static int check_patch(struct patch *patch)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed = ce_match_stat(active_cache[pos], &st);
|
changed = ce_match_stat(active_cache[pos], &st, 1);
|
||||||
if (changed)
|
if (changed)
|
||||||
return error("%s: does not match index",
|
return error("%s: does not match index",
|
||||||
old_name);
|
old_name);
|
||||||
|
|
6
cache.h
6
cache.h
|
@ -91,6 +91,7 @@ struct cache_entry {
|
||||||
#define CE_NAMEMASK (0x0fff)
|
#define CE_NAMEMASK (0x0fff)
|
||||||
#define CE_STAGEMASK (0x3000)
|
#define CE_STAGEMASK (0x3000)
|
||||||
#define CE_UPDATE (0x4000)
|
#define CE_UPDATE (0x4000)
|
||||||
|
#define CE_VALID (0x8000)
|
||||||
#define CE_STAGESHIFT 12
|
#define CE_STAGESHIFT 12
|
||||||
|
|
||||||
#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))
|
#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))
|
||||||
|
@ -144,8 +145,8 @@ extern int add_cache_entry(struct cache_entry *ce, int option);
|
||||||
extern int remove_cache_entry_at(int pos);
|
extern int remove_cache_entry_at(int pos);
|
||||||
extern int remove_file_from_cache(const char *path);
|
extern int remove_file_from_cache(const char *path);
|
||||||
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
|
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
|
||||||
extern int ce_match_stat(struct cache_entry *ce, struct stat *st);
|
extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int);
|
||||||
extern int ce_modified(struct cache_entry *ce, struct stat *st);
|
extern int ce_modified(struct cache_entry *ce, struct stat *st, int);
|
||||||
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
|
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
|
||||||
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type);
|
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type);
|
||||||
extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
|
extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
|
||||||
|
@ -161,6 +162,7 @@ extern int commit_index_file(struct cache_file *);
|
||||||
extern void rollback_index_file(struct cache_file *);
|
extern void rollback_index_file(struct cache_file *);
|
||||||
|
|
||||||
extern int trust_executable_bit;
|
extern int trust_executable_bit;
|
||||||
|
extern int assume_unchanged;
|
||||||
extern int only_use_symrefs;
|
extern int only_use_symrefs;
|
||||||
extern int diff_rename_limit_default;
|
extern int diff_rename_limit_default;
|
||||||
extern int shared_repository;
|
extern int shared_repository;
|
||||||
|
|
|
@ -116,6 +116,7 @@ int main(int argc, char **argv)
|
||||||
int all = 0;
|
int all = 0;
|
||||||
|
|
||||||
prefix = setup_git_directory();
|
prefix = setup_git_directory();
|
||||||
|
git_config(git_default_config);
|
||||||
prefix_length = prefix ? strlen(prefix) : 0;
|
prefix_length = prefix ? strlen(prefix) : 0;
|
||||||
|
|
||||||
if (read_cache() < 0) {
|
if (read_cache() < 0) {
|
||||||
|
|
5
config.c
5
config.c
|
@ -222,6 +222,11 @@ int git_default_config(const char *var, const char *value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(var, "core.ignorestat")) {
|
||||||
|
assume_unchanged = git_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(var, "core.symrefsonly")) {
|
if (!strcmp(var, "core.symrefsonly")) {
|
||||||
only_use_symrefs = git_config_bool(var, value);
|
only_use_symrefs = git_config_bool(var, value);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -193,7 +193,7 @@ int main(int argc, const char **argv)
|
||||||
show_file('-', ce);
|
show_file('-', ce);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
changed = ce_match_stat(ce, &st);
|
changed = ce_match_stat(ce, &st, 0);
|
||||||
if (!changed && !diff_options.find_copies_harder)
|
if (!changed && !diff_options.find_copies_harder)
|
||||||
continue;
|
continue;
|
||||||
oldmode = ntohl(ce->ce_mode);
|
oldmode = ntohl(ce->ce_mode);
|
||||||
|
|
|
@ -33,7 +33,7 @@ static int get_stat_data(struct cache_entry *ce,
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
changed = ce_match_stat(ce, &st);
|
changed = ce_match_stat(ce, &st, 0);
|
||||||
if (changed) {
|
if (changed) {
|
||||||
mode = create_ce_mode(st.st_mode);
|
mode = create_ce_mode(st.st_mode);
|
||||||
if (!trust_executable_bit &&
|
if (!trust_executable_bit &&
|
||||||
|
|
2
diff.c
2
diff.c
|
@ -311,7 +311,7 @@ static int work_tree_matches(const char *name, const unsigned char *sha1)
|
||||||
ce = active_cache[pos];
|
ce = active_cache[pos];
|
||||||
if ((lstat(name, &st) < 0) ||
|
if ((lstat(name, &st) < 0) ||
|
||||||
!S_ISREG(st.st_mode) || /* careful! */
|
!S_ISREG(st.st_mode) || /* careful! */
|
||||||
ce_match_stat(ce, &st) ||
|
ce_match_stat(ce, &st, 0) ||
|
||||||
memcmp(sha1, ce->sha1, 20))
|
memcmp(sha1, ce->sha1, 20))
|
||||||
return 0;
|
return 0;
|
||||||
/* we return 1 only when we can stat, it is a regular file,
|
/* we return 1 only when we can stat, it is a regular file,
|
||||||
|
|
2
entry.c
2
entry.c
|
@ -123,7 +123,7 @@ int checkout_entry(struct cache_entry *ce, struct checkout *state)
|
||||||
strcpy(path + len, ce->name);
|
strcpy(path + len, ce->name);
|
||||||
|
|
||||||
if (!lstat(path, &st)) {
|
if (!lstat(path, &st)) {
|
||||||
unsigned changed = ce_match_stat(ce, &st);
|
unsigned changed = ce_match_stat(ce, &st, 1);
|
||||||
if (!changed)
|
if (!changed)
|
||||||
return 0;
|
return 0;
|
||||||
if (!state->force) {
|
if (!state->force) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
char git_default_email[MAX_GITNAME];
|
char git_default_email[MAX_GITNAME];
|
||||||
char git_default_name[MAX_GITNAME];
|
char git_default_name[MAX_GITNAME];
|
||||||
int trust_executable_bit = 1;
|
int trust_executable_bit = 1;
|
||||||
|
int assume_unchanged = 0;
|
||||||
int only_use_symrefs = 0;
|
int only_use_symrefs = 0;
|
||||||
int repository_format_version = 0;
|
int repository_format_version = 0;
|
||||||
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
|
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
|
||||||
|
|
26
ls-files.c
26
ls-files.c
|
@ -20,6 +20,7 @@ static int show_unmerged = 0;
|
||||||
static int show_modified = 0;
|
static int show_modified = 0;
|
||||||
static int show_killed = 0;
|
static int show_killed = 0;
|
||||||
static int show_other_directories = 0;
|
static int show_other_directories = 0;
|
||||||
|
static int show_valid_bit = 0;
|
||||||
static int line_terminator = '\n';
|
static int line_terminator = '\n';
|
||||||
|
|
||||||
static int prefix_len = 0, prefix_offset = 0;
|
static int prefix_len = 0, prefix_offset = 0;
|
||||||
|
@ -457,6 +458,23 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
|
||||||
if (pathspec && !match(pathspec, ps_matched, ce->name, len))
|
if (pathspec && !match(pathspec, ps_matched, ce->name, len))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (tag && *tag && show_valid_bit &&
|
||||||
|
(ce->ce_flags & htons(CE_VALID))) {
|
||||||
|
static char alttag[4];
|
||||||
|
memcpy(alttag, tag, 3);
|
||||||
|
if (isalpha(tag[0]))
|
||||||
|
alttag[0] = tolower(tag[0]);
|
||||||
|
else if (tag[0] == '?')
|
||||||
|
alttag[0] = '!';
|
||||||
|
else {
|
||||||
|
alttag[0] = 'v';
|
||||||
|
alttag[1] = tag[0];
|
||||||
|
alttag[2] = ' ';
|
||||||
|
alttag[3] = 0;
|
||||||
|
}
|
||||||
|
tag = alttag;
|
||||||
|
}
|
||||||
|
|
||||||
if (!show_stage) {
|
if (!show_stage) {
|
||||||
fputs(tag, stdout);
|
fputs(tag, stdout);
|
||||||
write_name_quoted("", 0, ce->name + offset,
|
write_name_quoted("", 0, ce->name + offset,
|
||||||
|
@ -533,7 +551,7 @@ static void show_files(void)
|
||||||
err = lstat(ce->name, &st);
|
err = lstat(ce->name, &st);
|
||||||
if (show_deleted && err)
|
if (show_deleted && err)
|
||||||
show_ce_entry(tag_removed, ce);
|
show_ce_entry(tag_removed, ce);
|
||||||
if (show_modified && ce_modified(ce, &st))
|
if (show_modified && ce_modified(ce, &st, 0))
|
||||||
show_ce_entry(tag_modified, ce);
|
show_ce_entry(tag_modified, ce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,7 +624,7 @@ static void verify_pathspec(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char ls_files_usage[] =
|
static const char ls_files_usage[] =
|
||||||
"git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
|
"git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
|
||||||
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
|
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
|
||||||
"[ --exclude-per-directory=<filename> ] [--full-name] [--] [<file>]*";
|
"[ --exclude-per-directory=<filename> ] [--full-name] [--] [<file>]*";
|
||||||
|
|
||||||
|
@ -631,13 +649,15 @@ int main(int argc, const char **argv)
|
||||||
line_terminator = 0;
|
line_terminator = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "-t")) {
|
if (!strcmp(arg, "-t") || !strcmp(arg, "-v")) {
|
||||||
tag_cached = "H ";
|
tag_cached = "H ";
|
||||||
tag_unmerged = "M ";
|
tag_unmerged = "M ";
|
||||||
tag_removed = "R ";
|
tag_removed = "R ";
|
||||||
tag_modified = "C ";
|
tag_modified = "C ";
|
||||||
tag_other = "? ";
|
tag_other = "? ";
|
||||||
tag_killed = "K ";
|
tag_killed = "K ";
|
||||||
|
if (arg[1] == 'v')
|
||||||
|
show_valid_bit = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "-c") || !strcmp(arg, "--cached")) {
|
if (!strcmp(arg, "-c") || !strcmp(arg, "--cached")) {
|
||||||
|
|
28
read-cache.c
28
read-cache.c
|
@ -27,6 +27,9 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
|
||||||
ce->ce_uid = htonl(st->st_uid);
|
ce->ce_uid = htonl(st->st_uid);
|
||||||
ce->ce_gid = htonl(st->st_gid);
|
ce->ce_gid = htonl(st->st_gid);
|
||||||
ce->ce_size = htonl(st->st_size);
|
ce->ce_size = htonl(st->st_size);
|
||||||
|
|
||||||
|
if (assume_unchanged)
|
||||||
|
ce->ce_flags |= htons(CE_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ce_compare_data(struct cache_entry *ce, struct stat *st)
|
static int ce_compare_data(struct cache_entry *ce, struct stat *st)
|
||||||
|
@ -146,9 +149,18 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ce_match_stat(struct cache_entry *ce, struct stat *st)
|
int ce_match_stat(struct cache_entry *ce, struct stat *st, int ignore_valid)
|
||||||
{
|
{
|
||||||
unsigned int changed = ce_match_stat_basic(ce, st);
|
unsigned int changed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If it's marked as always valid in the index, it's
|
||||||
|
* valid whatever the checked-out copy says.
|
||||||
|
*/
|
||||||
|
if (!ignore_valid && (ce->ce_flags & htons(CE_VALID)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
changed = ce_match_stat_basic(ce, st);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Within 1 second of this sequence:
|
* Within 1 second of this sequence:
|
||||||
|
@ -164,7 +176,7 @@ int ce_match_stat(struct cache_entry *ce, struct stat *st)
|
||||||
* effectively mean we can make at most one commit per second,
|
* effectively mean we can make at most one commit per second,
|
||||||
* which is not acceptable. Instead, we check cache entries
|
* which is not acceptable. Instead, we check cache entries
|
||||||
* whose mtime are the same as the index file timestamp more
|
* whose mtime are the same as the index file timestamp more
|
||||||
* careful than others.
|
* carefully than others.
|
||||||
*/
|
*/
|
||||||
if (!changed &&
|
if (!changed &&
|
||||||
index_file_timestamp &&
|
index_file_timestamp &&
|
||||||
|
@ -174,10 +186,10 @@ int ce_match_stat(struct cache_entry *ce, struct stat *st)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ce_modified(struct cache_entry *ce, struct stat *st)
|
int ce_modified(struct cache_entry *ce, struct stat *st, int really)
|
||||||
{
|
{
|
||||||
int changed, changed_fs;
|
int changed, changed_fs;
|
||||||
changed = ce_match_stat(ce, st);
|
changed = ce_match_stat(ce, st, really);
|
||||||
if (!changed)
|
if (!changed)
|
||||||
return 0;
|
return 0;
|
||||||
/*
|
/*
|
||||||
|
@ -233,6 +245,11 @@ int cache_name_compare(const char *name1, int flags1, const char *name2, int fla
|
||||||
return -1;
|
return -1;
|
||||||
if (len1 > len2)
|
if (len1 > len2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* Compare stages */
|
||||||
|
flags1 &= CE_STAGEMASK;
|
||||||
|
flags2 &= CE_STAGEMASK;
|
||||||
|
|
||||||
if (flags1 < flags2)
|
if (flags1 < flags2)
|
||||||
return -1;
|
return -1;
|
||||||
if (flags1 > flags2)
|
if (flags1 > flags2)
|
||||||
|
@ -430,6 +447,7 @@ int add_cache_entry(struct cache_entry *ce, int option)
|
||||||
int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
|
int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
|
||||||
int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
|
int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
|
||||||
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
|
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
|
||||||
|
|
||||||
pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
|
pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
|
||||||
|
|
||||||
/* existing match? Just replace it. */
|
/* existing match? Just replace it. */
|
||||||
|
|
|
@ -349,7 +349,7 @@ static void verify_uptodate(struct cache_entry *ce)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!lstat(ce->name, &st)) {
|
if (!lstat(ce->name, &st)) {
|
||||||
unsigned changed = ce_match_stat(ce, &st);
|
unsigned changed = ce_match_stat(ce, &st, 1);
|
||||||
if (!changed)
|
if (!changed)
|
||||||
return;
|
return;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
|
@ -23,6 +23,10 @@ static int quiet; /* --refresh needing update is not error */
|
||||||
static int info_only;
|
static int info_only;
|
||||||
static int force_remove;
|
static int force_remove;
|
||||||
static int verbose;
|
static int verbose;
|
||||||
|
static int mark_valid_only = 0;
|
||||||
|
#define MARK_VALID 1
|
||||||
|
#define UNMARK_VALID 2
|
||||||
|
|
||||||
|
|
||||||
/* Three functions to allow overloaded pointer return; see linux/err.h */
|
/* Three functions to allow overloaded pointer return; see linux/err.h */
|
||||||
static inline void *ERR_PTR(long error)
|
static inline void *ERR_PTR(long error)
|
||||||
|
@ -53,6 +57,25 @@ static void report(const char *fmt, ...)
|
||||||
va_end(vp);
|
va_end(vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mark_valid(const char *path)
|
||||||
|
{
|
||||||
|
int namelen = strlen(path);
|
||||||
|
int pos = cache_name_pos(path, namelen);
|
||||||
|
if (0 <= pos) {
|
||||||
|
switch (mark_valid_only) {
|
||||||
|
case MARK_VALID:
|
||||||
|
active_cache[pos]->ce_flags |= htons(CE_VALID);
|
||||||
|
break;
|
||||||
|
case UNMARK_VALID:
|
||||||
|
active_cache[pos]->ce_flags &= ~htons(CE_VALID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
active_cache_changed = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int add_file_to_cache(const char *path)
|
static int add_file_to_cache(const char *path)
|
||||||
{
|
{
|
||||||
int size, namelen, option, status;
|
int size, namelen, option, status;
|
||||||
|
@ -94,6 +117,7 @@ static int add_file_to_cache(const char *path)
|
||||||
ce = xmalloc(size);
|
ce = xmalloc(size);
|
||||||
memset(ce, 0, size);
|
memset(ce, 0, size);
|
||||||
memcpy(ce->name, path, namelen);
|
memcpy(ce->name, path, namelen);
|
||||||
|
ce->ce_flags = htons(namelen);
|
||||||
fill_stat_cache_info(ce, &st);
|
fill_stat_cache_info(ce, &st);
|
||||||
|
|
||||||
ce->ce_mode = create_ce_mode(st.st_mode);
|
ce->ce_mode = create_ce_mode(st.st_mode);
|
||||||
|
@ -105,7 +129,6 @@ static int add_file_to_cache(const char *path)
|
||||||
if (0 <= pos)
|
if (0 <= pos)
|
||||||
ce->ce_mode = active_cache[pos]->ce_mode;
|
ce->ce_mode = active_cache[pos]->ce_mode;
|
||||||
}
|
}
|
||||||
ce->ce_flags = htons(namelen);
|
|
||||||
|
|
||||||
if (index_path(ce->sha1, path, &st, !info_only))
|
if (index_path(ce->sha1, path, &st, !info_only))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -128,7 +151,7 @@ static int add_file_to_cache(const char *path)
|
||||||
* For example, you'd want to do this after doing a "git-read-tree",
|
* For example, you'd want to do this after doing a "git-read-tree",
|
||||||
* to link up the stat cache details with the proper files.
|
* to link up the stat cache details with the proper files.
|
||||||
*/
|
*/
|
||||||
static struct cache_entry *refresh_entry(struct cache_entry *ce)
|
static struct cache_entry *refresh_entry(struct cache_entry *ce, int really)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct cache_entry *updated;
|
struct cache_entry *updated;
|
||||||
|
@ -137,21 +160,36 @@ static struct cache_entry *refresh_entry(struct cache_entry *ce)
|
||||||
if (lstat(ce->name, &st) < 0)
|
if (lstat(ce->name, &st) < 0)
|
||||||
return ERR_PTR(-errno);
|
return ERR_PTR(-errno);
|
||||||
|
|
||||||
changed = ce_match_stat(ce, &st);
|
changed = ce_match_stat(ce, &st, really);
|
||||||
if (!changed)
|
if (!changed) {
|
||||||
return NULL;
|
if (really && assume_unchanged &&
|
||||||
|
!(ce->ce_flags & htons(CE_VALID)))
|
||||||
|
; /* mark this one VALID again */
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ce_modified(ce, &st))
|
if (ce_modified(ce, &st, really))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
size = ce_size(ce);
|
size = ce_size(ce);
|
||||||
updated = xmalloc(size);
|
updated = xmalloc(size);
|
||||||
memcpy(updated, ce, size);
|
memcpy(updated, ce, size);
|
||||||
fill_stat_cache_info(updated, &st);
|
fill_stat_cache_info(updated, &st);
|
||||||
|
|
||||||
|
/* In this case, if really is not set, we should leave
|
||||||
|
* CE_VALID bit alone. Otherwise, paths marked with
|
||||||
|
* --no-assume-unchanged (i.e. things to be edited) will
|
||||||
|
* reacquire CE_VALID bit automatically, which is not
|
||||||
|
* really what we want.
|
||||||
|
*/
|
||||||
|
if (!really && assume_unchanged && !(ce->ce_flags & htons(CE_VALID)))
|
||||||
|
updated->ce_flags &= ~htons(CE_VALID);
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int refresh_cache(void)
|
static int refresh_cache(int really)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int has_errors = 0;
|
int has_errors = 0;
|
||||||
|
@ -171,12 +209,19 @@ static int refresh_cache(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = refresh_entry(ce);
|
new = refresh_entry(ce, really);
|
||||||
if (!new)
|
if (!new)
|
||||||
continue;
|
continue;
|
||||||
if (IS_ERR(new)) {
|
if (IS_ERR(new)) {
|
||||||
if (not_new && PTR_ERR(new) == -ENOENT)
|
if (not_new && PTR_ERR(new) == -ENOENT)
|
||||||
continue;
|
continue;
|
||||||
|
if (really && PTR_ERR(new) == -EINVAL) {
|
||||||
|
/* If we are doing --really-refresh that
|
||||||
|
* means the index is not valid anymore.
|
||||||
|
*/
|
||||||
|
ce->ce_flags &= ~htons(CE_VALID);
|
||||||
|
active_cache_changed = 1;
|
||||||
|
}
|
||||||
if (quiet)
|
if (quiet)
|
||||||
continue;
|
continue;
|
||||||
printf("%s: needs update\n", ce->name);
|
printf("%s: needs update\n", ce->name);
|
||||||
|
@ -274,6 +319,8 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
|
||||||
memcpy(ce->name, path, len);
|
memcpy(ce->name, path, len);
|
||||||
ce->ce_flags = create_ce_flags(len, stage);
|
ce->ce_flags = create_ce_flags(len, stage);
|
||||||
ce->ce_mode = create_ce_mode(mode);
|
ce->ce_mode = create_ce_mode(mode);
|
||||||
|
if (assume_unchanged)
|
||||||
|
ce->ce_flags |= htons(CE_VALID);
|
||||||
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
|
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
|
||||||
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
|
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
|
||||||
if (add_cache_entry(ce, option))
|
if (add_cache_entry(ce, option))
|
||||||
|
@ -317,6 +364,12 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
|
||||||
fprintf(stderr, "Ignoring path %s\n", path);
|
fprintf(stderr, "Ignoring path %s\n", path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mark_valid_only) {
|
||||||
|
if (mark_valid(p))
|
||||||
|
die("Unable to mark file %s", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (force_remove) {
|
if (force_remove) {
|
||||||
if (remove_file_from_cache(p))
|
if (remove_file_from_cache(p))
|
||||||
die("git-update-index: unable to remove %s", path);
|
die("git-update-index: unable to remove %s", path);
|
||||||
|
@ -467,7 +520,11 @@ int main(int argc, const char **argv)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(path, "--refresh")) {
|
if (!strcmp(path, "--refresh")) {
|
||||||
has_errors |= refresh_cache();
|
has_errors |= refresh_cache(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(path, "--really-refresh")) {
|
||||||
|
has_errors |= refresh_cache(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(path, "--cacheinfo")) {
|
if (!strcmp(path, "--cacheinfo")) {
|
||||||
|
@ -493,6 +550,14 @@ int main(int argc, const char **argv)
|
||||||
die("git-update-index: %s cannot chmod %s", path, argv[i]);
|
die("git-update-index: %s cannot chmod %s", path, argv[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(path, "--assume-unchanged")) {
|
||||||
|
mark_valid_only = MARK_VALID;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(path, "--no-assume-unchanged")) {
|
||||||
|
mark_valid_only = UNMARK_VALID;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(path, "--info-only")) {
|
if (!strcmp(path, "--info-only")) {
|
||||||
info_only = 1;
|
info_only = 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -111,7 +111,7 @@ int main(int argc, char **argv)
|
||||||
funny = 0;
|
funny = 0;
|
||||||
for (i = 0; i < entries; i++) {
|
for (i = 0; i < entries; i++) {
|
||||||
struct cache_entry *ce = active_cache[i];
|
struct cache_entry *ce = active_cache[i];
|
||||||
if (ntohs(ce->ce_flags) & ~CE_NAMEMASK) {
|
if (ce_stage(ce)) {
|
||||||
if (10 < ++funny) {
|
if (10 < ++funny) {
|
||||||
fprintf(stderr, "...\n");
|
fprintf(stderr, "...\n");
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue