Libify the index refresh logic

This cleans up and libifies the "git update-index --[really-]refresh"
functionality. This will be eventually required for eventually doing the
"commit" and "status" commands as built-ins.

It really just moves "refresh_index()" from update-index.c to
read-cache.c, but it also has to change the calling convention so that the
function uses a "unsigned int flags" argument instead of various static
flags variables for passing down the information about whether to be quiet
or not, and allow unmerged entries etc.

That actually cleans up update-index.c too, since it turns out that all
those flags were really specific to that one function of the index update,
so they shouldn't have had file-scope visibility even before.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Linus Torvalds 2006-05-19 09:56:35 -07:00 committed by Junio C Hamano
parent c3c8835fbb
commit 405e5b2fe0
3 changed files with 129 additions and 122 deletions

View File

@ -158,6 +158,12 @@ extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_o
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
#define REFRESH_REALLY 0x0001 /* ignore_valid */
#define REFRESH_UNMERGED 0x0002 /* allow unmerged */
#define REFRESH_QUIET 0x0004 /* be quiet about it */
#define REFRESH_IGNORE_MISSING 0x0008 /* ignore non-existent */
extern int refresh_cache(unsigned int flags);
struct cache_file {
struct cache_file *next;
char lockfile[PATH_MAX];

View File

@ -496,6 +496,123 @@ int add_cache_entry(struct cache_entry *ce, int option)
return 0;
}
/* Three functions to allow overloaded pointer return; see linux/err.h */
static inline void *ERR_PTR(long error)
{
return (void *) error;
}
static inline long PTR_ERR(const void *ptr)
{
return (long) ptr;
}
static inline long IS_ERR(const void *ptr)
{
return (unsigned long)ptr > (unsigned long)-1000L;
}
/*
* "refresh" does not calculate a new sha1 file or bring the
* cache up-to-date for mode/content changes. But what it
* _does_ do is to "re-match" the stat information of a file
* with the cache, so that you can refresh the cache for a
* file that hasn't been changed but where the stat entry is
* out of date.
*
* 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.
*/
static struct cache_entry *refresh_entry(struct cache_entry *ce, int really)
{
struct stat st;
struct cache_entry *updated;
int changed, size;
if (lstat(ce->name, &st) < 0)
return ERR_PTR(-errno);
changed = ce_match_stat(ce, &st, really);
if (!changed) {
if (really && assume_unchanged &&
!(ce->ce_flags & htons(CE_VALID)))
; /* mark this one VALID again */
else
return NULL;
}
if (ce_modified(ce, &st, really))
return ERR_PTR(-EINVAL);
size = ce_size(ce);
updated = xmalloc(size);
memcpy(updated, ce, size);
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;
}
int refresh_cache(unsigned int flags)
{
int i;
int has_errors = 0;
int really = (flags & REFRESH_REALLY) != 0;
int allow_unmerged = (flags & REFRESH_UNMERGED) != 0;
int quiet = (flags & REFRESH_QUIET) != 0;
int not_new = (flags & REFRESH_IGNORE_MISSING) != 0;
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce, *new;
ce = active_cache[i];
if (ce_stage(ce)) {
while ((i < active_nr) &&
! strcmp(active_cache[i]->name, ce->name))
i++;
i--;
if (allow_unmerged)
continue;
printf("%s: needs merge\n", ce->name);
has_errors = 1;
continue;
}
new = refresh_entry(ce, really);
if (!new)
continue;
if (IS_ERR(new)) {
if (not_new && PTR_ERR(new) == -ENOENT)
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)
continue;
printf("%s: needs update\n", ce->name);
has_errors = 1;
continue;
}
active_cache_changed = 1;
/* You can NOT just free active_cache[i] here, since it
* might not be necessarily malloc()ed but can also come
* from mmap(). */
active_cache[i] = new;
}
return has_errors;
}
static int verify_hdr(struct cache_header *hdr, unsigned long size)
{
SHA_CTX c;

View File

@ -18,9 +18,6 @@
static int allow_add;
static int allow_remove;
static int allow_replace;
static int allow_unmerged; /* --refresh needing merge is not error */
static int not_new; /* --refresh not having working tree files is not error */
static int quiet; /* --refresh needing update is not error */
static int info_only;
static int force_remove;
static int verbose;
@ -28,23 +25,6 @@ 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 */
static inline void *ERR_PTR(long error)
{
return (void *) error;
}
static inline long PTR_ERR(const void *ptr)
{
return (long) ptr;
}
static inline long IS_ERR(const void *ptr)
{
return (unsigned long)ptr > (unsigned long)-1000L;
}
static void report(const char *fmt, ...)
{
va_list vp;
@ -140,103 +120,6 @@ static int add_file_to_cache(const char *path)
return 0;
}
/*
* "refresh" does not calculate a new sha1 file or bring the
* cache up-to-date for mode/content changes. But what it
* _does_ do is to "re-match" the stat information of a file
* with the cache, so that you can refresh the cache for a
* file that hasn't been changed but where the stat entry is
* out of date.
*
* 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.
*/
static struct cache_entry *refresh_entry(struct cache_entry *ce, int really)
{
struct stat st;
struct cache_entry *updated;
int changed, size;
if (lstat(ce->name, &st) < 0)
return ERR_PTR(-errno);
changed = ce_match_stat(ce, &st, really);
if (!changed) {
if (really && assume_unchanged &&
!(ce->ce_flags & htons(CE_VALID)))
; /* mark this one VALID again */
else
return NULL;
}
if (ce_modified(ce, &st, really))
return ERR_PTR(-EINVAL);
size = ce_size(ce);
updated = xmalloc(size);
memcpy(updated, ce, size);
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;
}
static int refresh_cache(int really)
{
int i;
int has_errors = 0;
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce, *new;
ce = active_cache[i];
if (ce_stage(ce)) {
while ((i < active_nr) &&
! strcmp(active_cache[i]->name, ce->name))
i++;
i--;
if (allow_unmerged)
continue;
printf("%s: needs merge\n", ce->name);
has_errors = 1;
continue;
}
new = refresh_entry(ce, really);
if (!new)
continue;
if (IS_ERR(new)) {
if (not_new && PTR_ERR(new) == -ENOENT)
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)
continue;
printf("%s: needs update\n", ce->name);
has_errors = 1;
continue;
}
active_cache_changed = 1;
/* You can NOT just free active_cache[i] here, since it
* might not be necessarily malloc()ed but can also come
* from mmap(). */
active_cache[i] = new;
}
return has_errors;
}
/*
* We fundamentally don't like some paths: we don't want
* dot or dot-dot anywhere, and for obvious reasons don't
@ -653,6 +536,7 @@ int main(int argc, const char **argv)
const char *prefix = setup_git_directory();
int prefix_length = prefix ? strlen(prefix) : 0;
char set_executable_bit = 0;
unsigned int refresh_flags = 0;
git_config(git_default_config);
@ -673,7 +557,7 @@ int main(int argc, const char **argv)
continue;
}
if (!strcmp(path, "-q")) {
quiet = 1;
refresh_flags |= REFRESH_QUIET;
continue;
}
if (!strcmp(path, "--add")) {
@ -689,15 +573,15 @@ int main(int argc, const char **argv)
continue;
}
if (!strcmp(path, "--unmerged")) {
allow_unmerged = 1;
refresh_flags |= REFRESH_UNMERGED;
continue;
}
if (!strcmp(path, "--refresh")) {
has_errors |= refresh_cache(0);
has_errors |= refresh_cache(refresh_flags);
continue;
}
if (!strcmp(path, "--really-refresh")) {
has_errors |= refresh_cache(1);
has_errors |= refresh_cache(REFRESH_REALLY | refresh_flags);
continue;
}
if (!strcmp(path, "--cacheinfo")) {
@ -770,7 +654,7 @@ int main(int argc, const char **argv)
goto finish;
}
if (!strcmp(path, "--ignore-missing")) {
not_new = 1;
refresh_flags |= REFRESH_IGNORE_MISSING;
continue;
}
if (!strcmp(path, "--verbose")) {