diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-18 10:16:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-18 10:16:14 -0700 |
commit | 1024932f019905ff1a9e06e5acbee441919d4d05 (patch) | |
tree | 6017a62faea36398641decacd149461b33183074 | |
parent | b58f23b38a9a9f28d751311353819d3cdf6a86da (diff) | |
download | git-1024932f019905ff1a9e06e5acbee441919d4d05.tar.gz |
fsck-cache: walk the 'refs' directory if the user doesn't give any
explicit references for reachability analysis.
We already had that as separate logic in git-prune-script, so this
is not a new special case - it's an old special case moved into
fsck, making normal usage be much simpler.
-rw-r--r-- | fsck-cache.c | 83 | ||||
-rwxr-xr-x | git-prune-script | 13 |
2 files changed, 74 insertions, 22 deletions
diff --git a/fsck-cache.c b/fsck-cache.c index a00702b79f..d2aff8c643 100644 --- a/fsck-cache.c +++ b/fsck-cache.c @@ -296,6 +296,70 @@ static int fsck_dir(int i, char *path) return 0; } +static void read_sha1_reference(const char *path) +{ + char hexname[60]; + unsigned char sha1[20]; + int fd = open(path, O_RDONLY), len; + struct object *obj; + + if (fd < 0) + return; + + len = read(fd, hexname, sizeof(hexname)); + close(fd); + if (len < 40) + return; + + if (get_sha1_hex(hexname, sha1) < 0) + return; + + obj = lookup_object(sha1); + obj->used = 1; + mark_reachable(obj, REACHABLE); +} + +static void find_file_objects(const char *base, const char *name) +{ + int baselen = strlen(base); + int namelen = strlen(name); + char *path = xmalloc(baselen + namelen + 2); + struct stat st; + + memcpy(path, base, baselen); + path[baselen] = '/'; + memcpy(path + baselen + 1, name, namelen+1); + if (stat(path, &st) < 0) + return; + + /* + * Recurse into directories + */ + if (S_ISDIR(st.st_mode)) { + DIR *dir = opendir(path); + if (dir) { + struct dirent *de; + while ((de = readdir(dir)) != NULL) { + if (de->d_name[0] == '.') + continue; + find_file_objects(path, de->d_name); + } + closedir(dir); + } + return; + } + if (S_ISREG(st.st_mode)) { + read_sha1_reference(path); + return; + } +} + +static void get_default_heads(void) +{ + char *git_dir = gitenv(GIT_DIR_ENVIRONMENT) ? : DEFAULT_GIT_DIR_ENVIRONMENT; + find_file_objects(git_dir, "refs"); +} + int main(int argc, char **argv) { int i, heads; @@ -354,6 +418,16 @@ int main(int argc, char **argv) error("expected sha1, got %s", arg); } + /* + * If we've been asked to do reachability without any explicit + * head information, do the default ones from .git/refs. We also + * consider the index file in this case (ie this implies --cache). + */ + if (show_unreachable && !heads) { + get_default_heads(); + keep_cache_objects = 1; + } + if (keep_cache_objects) { int i; read_cache(); @@ -368,15 +442,6 @@ int main(int argc, char **argv) } } - if (!heads && !keep_cache_objects) { - if (show_unreachable) { - fprintf(stderr, "unable to do reachability without a head nor --cache\n"); - show_unreachable = 0; - } - if (!heads) - fprintf(stderr, "expect dangling commits - potential heads - due to lack of head information\n"); - } - check_connectivity(); return 0; } diff --git a/git-prune-script b/git-prune-script index 1a97ccc91d..ec9f72de79 100755 --- a/git-prune-script +++ b/git-prune-script @@ -14,19 +14,6 @@ done : ${GIT_DIR=.git} : ${GIT_OBJECT_DIRECTORY="${SHA1_FILE_DIRECTORY-"$GIT_DIR/objects"}"} -# Defaulting to include .git/refs/*/* may be debatable from the -# purist POV but power users can always give explicit parameters -# to the script anyway. - -case "$#" in -0) - x_40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' - x_40="$x_40$x_40$x_40$x_40$x_40$x_40$x_40$x_40" - set x $(sed -ne "/^$x_40\$/p" \ - "$GIT_DIR"/HEAD "$GIT_DIR"/refs/*/* /dev/null 2>/dev/null) - shift ;; -esac - git-fsck-cache --cache --unreachable "$@" | sed -ne '/unreachable /{ s/unreachable [^ ][^ ]* // |