From: Junio C Hamano Date: Fri, 19 May 2006 23:26:01 +0000 (-0700) Subject: Merge branch 'ts/doctar' X-Git-Tag: v1.4.0-rc1~119 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/3532998f407c5b4563ef15ffc52fe54e1f194993?hp=52db0495dcb88f38590bc00607052fc5758b07d1 Merge branch 'ts/doctar' * ts/doctar: Documentation/Makefile: create tarballs for the man pages and html files --- diff --git a/Makefile b/Makefile index c33a4d2b3e..e804010296 100644 --- a/Makefile +++ b/Makefile @@ -154,7 +154,7 @@ PROGRAMS = \ git-convert-objects$X git-diff-files$X \ git-diff-index$X git-diff-stages$X \ git-diff-tree$X git-fetch-pack$X git-fsck-objects$X \ - git-hash-object$X git-index-pack$X git-init-db$X git-local-fetch$X \ + git-hash-object$X git-index-pack$X git-local-fetch$X \ git-ls-files$X git-ls-tree$X git-mailinfo$X git-merge-base$X \ git-merge-index$X git-mktag$X git-mktree$X git-pack-objects$X git-patch-id$X \ git-peek-remote$X git-prune-packed$X git-read-tree$X \ @@ -170,7 +170,8 @@ PROGRAMS = \ BUILT_INS = git-log$X git-whatchanged$X git-show$X \ git-count-objects$X git-diff$X git-push$X \ - git-grep$X git-rev-list$X git-check-ref-format$X + git-grep$X git-rev-list$X git-check-ref-format$X \ + git-init-db$X # what 'all' will build and 'install' will install, in gitexecdir ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) @@ -218,7 +219,8 @@ LIB_OBJS = \ BUILTIN_OBJS = \ builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \ - builtin-grep.o builtin-rev-list.o builtin-check-ref-format.o + builtin-grep.o builtin-rev-list.o builtin-check-ref-format.o \ + builtin-init-db.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) LIBS = $(GITLIBS) -lz @@ -473,6 +475,7 @@ strip: $(PROGRAMS) git$X git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) $(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ + -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' \ $(ALL_CFLAGS) -o $@ $(filter %.c,$^) \ $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) @@ -565,10 +568,6 @@ git-http-push$X: revision.o http.o http-push.o $(LIB_FILE) $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) -init-db.o: init-db.c - $(CC) -c $(ALL_CFLAGS) \ - -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c - $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(GITLIBS) $(DIFF_OBJS): diffcore.h diff --git a/builtin-init-db.c b/builtin-init-db.c new file mode 100644 index 0000000000..2a1384ccb0 --- /dev/null +++ b/builtin-init-db.c @@ -0,0 +1,293 @@ +/* + * GIT - The information manager from hell + * + * Copyright (C) Linus Torvalds, 2005 + */ +#include "cache.h" +#include "builtin.h" + +#ifndef DEFAULT_GIT_TEMPLATE_DIR +#define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/" +#endif + +static void safe_create_dir(const char *dir, int share) +{ + if (mkdir(dir, 0777) < 0) { + if (errno != EEXIST) { + perror(dir); + exit(1); + } + } + else if (share && adjust_shared_perm(dir)) + die("Could not make %s writable by group\n", dir); +} + +static int copy_file(const char *dst, const char *src, int mode) +{ + int fdi, fdo, status; + + mode = (mode & 0111) ? 0777 : 0666; + if ((fdi = open(src, O_RDONLY)) < 0) + return fdi; + if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { + close(fdi); + return fdo; + } + status = copy_fd(fdi, fdo); + close(fdo); + + if (!status && adjust_shared_perm(dst)) + return -1; + + return status; +} + +static void copy_templates_1(char *path, int baselen, + char *template, int template_baselen, + DIR *dir) +{ + struct dirent *de; + + /* Note: if ".git/hooks" file exists in the repository being + * re-initialized, /etc/core-git/templates/hooks/update would + * cause git-init-db to fail here. I think this is sane but + * it means that the set of templates we ship by default, along + * with the way the namespace under .git/ is organized, should + * be really carefully chosen. + */ + safe_create_dir(path, 1); + while ((de = readdir(dir)) != NULL) { + struct stat st_git, st_template; + int namelen; + int exists = 0; + + if (de->d_name[0] == '.') + continue; + namelen = strlen(de->d_name); + if ((PATH_MAX <= baselen + namelen) || + (PATH_MAX <= template_baselen + namelen)) + die("insanely long template name %s", de->d_name); + memcpy(path + baselen, de->d_name, namelen+1); + memcpy(template + template_baselen, de->d_name, namelen+1); + if (lstat(path, &st_git)) { + if (errno != ENOENT) + die("cannot stat %s", path); + } + else + exists = 1; + + if (lstat(template, &st_template)) + die("cannot stat template %s", template); + + if (S_ISDIR(st_template.st_mode)) { + DIR *subdir = opendir(template); + int baselen_sub = baselen + namelen; + int template_baselen_sub = template_baselen + namelen; + if (!subdir) + die("cannot opendir %s", template); + path[baselen_sub++] = + template[template_baselen_sub++] = '/'; + path[baselen_sub] = + template[template_baselen_sub] = 0; + copy_templates_1(path, baselen_sub, + template, template_baselen_sub, + subdir); + closedir(subdir); + } + else if (exists) + continue; + else if (S_ISLNK(st_template.st_mode)) { + char lnk[256]; + int len; + len = readlink(template, lnk, sizeof(lnk)); + if (len < 0) + die("cannot readlink %s", template); + if (sizeof(lnk) <= len) + die("insanely long symlink %s", template); + lnk[len] = 0; + if (symlink(lnk, path)) + die("cannot symlink %s %s", lnk, path); + } + else if (S_ISREG(st_template.st_mode)) { + if (copy_file(path, template, st_template.st_mode)) + die("cannot copy %s to %s", template, path); + } + else + error("ignoring template %s", template); + } +} + +static void copy_templates(const char *git_dir, int len, const char *template_dir) +{ + char path[PATH_MAX]; + char template_path[PATH_MAX]; + int template_len; + DIR *dir; + + if (!template_dir) + template_dir = DEFAULT_GIT_TEMPLATE_DIR; + strcpy(template_path, template_dir); + template_len = strlen(template_path); + if (template_path[template_len-1] != '/') { + template_path[template_len++] = '/'; + template_path[template_len] = 0; + } + dir = opendir(template_path); + if (!dir) { + fprintf(stderr, "warning: templates not found %s\n", + template_dir); + return; + } + + /* Make sure that template is from the correct vintage */ + strcpy(template_path + template_len, "config"); + repository_format_version = 0; + git_config_from_file(check_repository_format_version, + template_path); + template_path[template_len] = 0; + + if (repository_format_version && + repository_format_version != GIT_REPO_VERSION) { + fprintf(stderr, "warning: not copying templates of " + "a wrong format version %d from '%s'\n", + repository_format_version, + template_dir); + closedir(dir); + return; + } + + memcpy(path, git_dir, len); + path[len] = 0; + copy_templates_1(path, len, + template_path, template_len, + dir); + closedir(dir); +} + +static void create_default_files(const char *git_dir, const char *template_path) +{ + unsigned len = strlen(git_dir); + static char path[PATH_MAX]; + unsigned char sha1[20]; + struct stat st1; + char repo_version_string[10]; + + if (len > sizeof(path)-50) + die("insane git directory %s", git_dir); + memcpy(path, git_dir, len); + + if (len && path[len-1] != '/') + path[len++] = '/'; + + /* + * Create .git/refs/{heads,tags} + */ + strcpy(path + len, "refs"); + safe_create_dir(path, 1); + strcpy(path + len, "refs/heads"); + safe_create_dir(path, 1); + strcpy(path + len, "refs/tags"); + safe_create_dir(path, 1); + + /* First copy the templates -- we might have the default + * config file there, in which case we would want to read + * from it after installing. + */ + path[len] = 0; + copy_templates(path, len, template_path); + + git_config(git_default_config); + + /* + * Create the default symlink from ".git/HEAD" to the "master" + * branch, if it does not exist yet. + */ + strcpy(path + len, "HEAD"); + if (read_ref(path, sha1) < 0) { + if (create_symref(path, "refs/heads/master") < 0) + exit(1); + } + + /* This forces creation of new config file */ + sprintf(repo_version_string, "%d", GIT_REPO_VERSION); + git_config_set("core.repositoryformatversion", repo_version_string); + + path[len] = 0; + strcpy(path + len, "config"); + + /* Check filemode trustability */ + if (!lstat(path, &st1)) { + struct stat st2; + int filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && + !lstat(path, &st2) && + st1.st_mode != st2.st_mode); + git_config_set("core.filemode", + filemode ? "true" : "false"); + } +} + +static const char init_db_usage[] = +"git-init-db [--template=] [--shared]"; + +/* + * If you want to, you can share the DB area with any number of branches. + * That has advantages: you can save space by sharing all the SHA1 objects. + * On the other hand, it might just make lookup slower and messier. You + * be the judge. The default case is to have one DB per managed directory. + */ +int cmd_init_db(int argc, const char **argv, char **envp) +{ + const char *git_dir; + const char *sha1_dir; + const char *template_dir = NULL; + char *path; + int len, i; + + for (i = 1; i < argc; i++, argv++) { + const char *arg = argv[1]; + if (!strncmp(arg, "--template=", 11)) + template_dir = arg+11; + else if (!strcmp(arg, "--shared")) + shared_repository = 1; + else + die(init_db_usage); + } + + /* + * Set up the default .git directory contents + */ + git_dir = getenv(GIT_DIR_ENVIRONMENT); + if (!git_dir) { + git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; + fprintf(stderr, "defaulting to local storage area\n"); + } + safe_create_dir(git_dir, 0); + + /* Check to see if the repository version is right. + * Note that a newly created repository does not have + * config file, so this will not fail. What we are catching + * is an attempt to reinitialize new repository with an old tool. + */ + check_repository_format(); + + create_default_files(git_dir, template_dir); + + /* + * And set up the object store. + */ + sha1_dir = get_object_directory(); + len = strlen(sha1_dir); + path = xmalloc(len + 40); + memcpy(path, sha1_dir, len); + + safe_create_dir(sha1_dir, 1); + strcpy(path+len, "/pack"); + safe_create_dir(path, 1); + strcpy(path+len, "/info"); + safe_create_dir(path, 1); + + if (shared_repository) + git_config_set("core.sharedRepository", "true"); + + return 0; +} diff --git a/builtin-log.c b/builtin-log.c index 69f2911cb4..c4ceee0f98 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -19,6 +19,13 @@ static int cmd_log_wc(int argc, const char **argv, char **envp, rev->commit_format = CMIT_FMT_DEFAULT; rev->verbose_header = 1; argc = setup_revisions(argc, argv, rev, "HEAD"); + if (rev->always_show_header) { + if (rev->diffopt.pickaxe || rev->diffopt.filter) { + rev->always_show_header = 0; + if (rev->diffopt.output_format == DIFF_FORMAT_RAW) + rev->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT; + } + } if (argc > 1) die("unrecognized argument: %s", argv[1]); diff --git a/builtin.h b/builtin.h index ff559dec7e..60541262c4 100644 --- a/builtin.h +++ b/builtin.h @@ -26,5 +26,6 @@ extern int cmd_push(int argc, const char **argv, char **envp); extern int cmd_grep(int argc, const char **argv, char **envp); extern int cmd_rev_list(int argc, const char **argv, char **envp); extern int cmd_check_ref_format(int argc, const char **argv, char **envp); +extern int cmd_init_db(int argc, const char **argv, char **envp); #endif diff --git a/cache.h b/cache.h index 4b7a439253..afa8e4f0ac 100644 --- a/cache.h +++ b/cache.h @@ -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]; diff --git a/git.c b/git.c index d0650bb409..3216d311b2 100644 --- a/git.c +++ b/git.c @@ -51,6 +51,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) { "diff", cmd_diff }, { "grep", cmd_grep }, { "rev-list", cmd_rev_list }, + { "init-db", cmd_init_db }, { "check-ref-format", cmd_check_ref_format } }; int i; diff --git a/init-db.c b/init-db.c deleted file mode 100644 index ff294960f2..0000000000 --- a/init-db.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * GIT - The information manager from hell - * - * Copyright (C) Linus Torvalds, 2005 - */ -#include "cache.h" - -#ifndef DEFAULT_GIT_TEMPLATE_DIR -#define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/" -#endif - -static void safe_create_dir(const char *dir, int share) -{ - if (mkdir(dir, 0777) < 0) { - if (errno != EEXIST) { - perror(dir); - exit(1); - } - } - else if (share && adjust_shared_perm(dir)) - die("Could not make %s writable by group\n", dir); -} - -static int copy_file(const char *dst, const char *src, int mode) -{ - int fdi, fdo, status; - - mode = (mode & 0111) ? 0777 : 0666; - if ((fdi = open(src, O_RDONLY)) < 0) - return fdi; - if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { - close(fdi); - return fdo; - } - status = copy_fd(fdi, fdo); - close(fdo); - - if (!status && adjust_shared_perm(dst)) - return -1; - - return status; -} - -static void copy_templates_1(char *path, int baselen, - char *template, int template_baselen, - DIR *dir) -{ - struct dirent *de; - - /* Note: if ".git/hooks" file exists in the repository being - * re-initialized, /etc/core-git/templates/hooks/update would - * cause git-init-db to fail here. I think this is sane but - * it means that the set of templates we ship by default, along - * with the way the namespace under .git/ is organized, should - * be really carefully chosen. - */ - safe_create_dir(path, 1); - while ((de = readdir(dir)) != NULL) { - struct stat st_git, st_template; - int namelen; - int exists = 0; - - if (de->d_name[0] == '.') - continue; - namelen = strlen(de->d_name); - if ((PATH_MAX <= baselen + namelen) || - (PATH_MAX <= template_baselen + namelen)) - die("insanely long template name %s", de->d_name); - memcpy(path + baselen, de->d_name, namelen+1); - memcpy(template + template_baselen, de->d_name, namelen+1); - if (lstat(path, &st_git)) { - if (errno != ENOENT) - die("cannot stat %s", path); - } - else - exists = 1; - - if (lstat(template, &st_template)) - die("cannot stat template %s", template); - - if (S_ISDIR(st_template.st_mode)) { - DIR *subdir = opendir(template); - int baselen_sub = baselen + namelen; - int template_baselen_sub = template_baselen + namelen; - if (!subdir) - die("cannot opendir %s", template); - path[baselen_sub++] = - template[template_baselen_sub++] = '/'; - path[baselen_sub] = - template[template_baselen_sub] = 0; - copy_templates_1(path, baselen_sub, - template, template_baselen_sub, - subdir); - closedir(subdir); - } - else if (exists) - continue; - else if (S_ISLNK(st_template.st_mode)) { - char lnk[256]; - int len; - len = readlink(template, lnk, sizeof(lnk)); - if (len < 0) - die("cannot readlink %s", template); - if (sizeof(lnk) <= len) - die("insanely long symlink %s", template); - lnk[len] = 0; - if (symlink(lnk, path)) - die("cannot symlink %s %s", lnk, path); - } - else if (S_ISREG(st_template.st_mode)) { - if (copy_file(path, template, st_template.st_mode)) - die("cannot copy %s to %s", template, path); - } - else - error("ignoring template %s", template); - } -} - -static void copy_templates(const char *git_dir, int len, char *template_dir) -{ - char path[PATH_MAX]; - char template_path[PATH_MAX]; - int template_len; - DIR *dir; - - if (!template_dir) - template_dir = DEFAULT_GIT_TEMPLATE_DIR; - strcpy(template_path, template_dir); - template_len = strlen(template_path); - if (template_path[template_len-1] != '/') { - template_path[template_len++] = '/'; - template_path[template_len] = 0; - } - dir = opendir(template_path); - if (!dir) { - fprintf(stderr, "warning: templates not found %s\n", - template_dir); - return; - } - - /* Make sure that template is from the correct vintage */ - strcpy(template_path + template_len, "config"); - repository_format_version = 0; - git_config_from_file(check_repository_format_version, - template_path); - template_path[template_len] = 0; - - if (repository_format_version && - repository_format_version != GIT_REPO_VERSION) { - fprintf(stderr, "warning: not copying templates of " - "a wrong format version %d from '%s'\n", - repository_format_version, - template_dir); - closedir(dir); - return; - } - - memcpy(path, git_dir, len); - path[len] = 0; - copy_templates_1(path, len, - template_path, template_len, - dir); - closedir(dir); -} - -static void create_default_files(const char *git_dir, char *template_path) -{ - unsigned len = strlen(git_dir); - static char path[PATH_MAX]; - unsigned char sha1[20]; - struct stat st1; - char repo_version_string[10]; - - if (len > sizeof(path)-50) - die("insane git directory %s", git_dir); - memcpy(path, git_dir, len); - - if (len && path[len-1] != '/') - path[len++] = '/'; - - /* - * Create .git/refs/{heads,tags} - */ - strcpy(path + len, "refs"); - safe_create_dir(path, 1); - strcpy(path + len, "refs/heads"); - safe_create_dir(path, 1); - strcpy(path + len, "refs/tags"); - safe_create_dir(path, 1); - - /* First copy the templates -- we might have the default - * config file there, in which case we would want to read - * from it after installing. - */ - path[len] = 0; - copy_templates(path, len, template_path); - - git_config(git_default_config); - - /* - * Create the default symlink from ".git/HEAD" to the "master" - * branch, if it does not exist yet. - */ - strcpy(path + len, "HEAD"); - if (read_ref(path, sha1) < 0) { - if (create_symref(path, "refs/heads/master") < 0) - exit(1); - } - - /* This forces creation of new config file */ - sprintf(repo_version_string, "%d", GIT_REPO_VERSION); - git_config_set("core.repositoryformatversion", repo_version_string); - - path[len] = 0; - strcpy(path + len, "config"); - - /* Check filemode trustability */ - if (!lstat(path, &st1)) { - struct stat st2; - int filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && - !lstat(path, &st2) && - st1.st_mode != st2.st_mode); - git_config_set("core.filemode", - filemode ? "true" : "false"); - } -} - -static const char init_db_usage[] = -"git-init-db [--template=] [--shared]"; - -/* - * If you want to, you can share the DB area with any number of branches. - * That has advantages: you can save space by sharing all the SHA1 objects. - * On the other hand, it might just make lookup slower and messier. You - * be the judge. The default case is to have one DB per managed directory. - */ -int main(int argc, char **argv) -{ - const char *git_dir; - const char *sha1_dir; - char *path, *template_dir = NULL; - int len, i; - - for (i = 1; i < argc; i++, argv++) { - char *arg = argv[1]; - if (!strncmp(arg, "--template=", 11)) - template_dir = arg+11; - else if (!strcmp(arg, "--shared")) - shared_repository = 1; - else - die(init_db_usage); - } - - /* - * Set up the default .git directory contents - */ - git_dir = getenv(GIT_DIR_ENVIRONMENT); - if (!git_dir) { - git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; - fprintf(stderr, "defaulting to local storage area\n"); - } - safe_create_dir(git_dir, 0); - - /* Check to see if the repository version is right. - * Note that a newly created repository does not have - * config file, so this will not fail. What we are catching - * is an attempt to reinitialize new repository with an old tool. - */ - check_repository_format(); - - create_default_files(git_dir, template_dir); - - /* - * And set up the object store. - */ - sha1_dir = get_object_directory(); - len = strlen(sha1_dir); - path = xmalloc(len + 40); - memcpy(path, sha1_dir, len); - - safe_create_dir(sha1_dir, 1); - strcpy(path+len, "/pack"); - safe_create_dir(path, 1); - strcpy(path+len, "/info"); - safe_create_dir(path, 1); - - if (shared_repository) - git_config_set("core.sharedRepository", "true"); - - return 0; -} diff --git a/read-cache.c b/read-cache.c index a917ab0cfe..b95edcc14c 100644 --- a/read-cache.c +++ b/read-cache.c @@ -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; diff --git a/refs.c b/refs.c index 6c91ae6468..0f3491f871 100644 --- a/refs.c +++ b/refs.c @@ -220,12 +220,9 @@ static char *ref_lock_file_name(const char *ref) int get_ref_sha1(const char *ref, unsigned char *sha1) { - const char *filename; - if (check_ref_format(ref)) return -1; - filename = git_path("refs/%s", ref); - return read_ref(filename, sha1); + return read_ref(git_path("refs/%s", ref), sha1); } static int lock_ref_file(const char *filename, const char *lock_filename, diff --git a/update-index.c b/update-index.c index 3d7e02db2c..7d6de821e2 100644 --- a/update-index.c +++ b/update-index.c @@ -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")) {