diff options
-rw-r--r-- | Documentation/git-rev-parse.txt | 35 | ||||
-rw-r--r-- | fetch.c | 2 | ||||
-rwxr-xr-x | git-add.sh | 32 | ||||
-rw-r--r-- | http-fetch.c | 45 | ||||
-rw-r--r-- | rev-parse.c | 16 | ||||
-rw-r--r-- | update-index.c | 36 |
6 files changed, 146 insertions, 20 deletions
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index fa64c5a561..067e4f0025 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -76,6 +76,41 @@ OPTIONS Flags and parameters to be parsed. +SPECIFYING REVISIONS +-------------------- + +A revision parameter typically names a commit object. They use +what is called an 'extended SHA1' syntax. + +* The full SHA1 object name (40-byte hexadecimal string), or + a substring of such that is unique within the repository. + E.g. dae86e1950b1277e545cee180551750029cfe735 and dae86e both + name the same commit object if there are no other object in + your repository whose object name starts with dae86e. + +* A symbolic ref name. E.g. 'master' typically means the commit + object referenced by $GIT_DIR/refs/heads/master. If you + happen to have both heads/master and tags/master, you can + explicitly say 'heads/master' to tell GIT which one you mean. + +* A suffix '^' to a revision parameter means the first parent of + that commit object. '^<n>' means the <n>th parent (i.e. + 'rev^' + is equivalent to 'rev^1'). As a special rule, + 'rev^0' means the commit itself and is used when 'rev' is the + object name of a tag object that refers to a commit object. + +* A suffix '~<n>' to a revision parameter means the commit + object that is the <n>th generation grand-parent of the named + commit object, following only the first parent. I.e. rev~3 is + equivalent to rev^^^ which is equivalent to rev^1^1^1. + +'git-rev-parse' also accepts a prefix '^' to revision parameter, +which is passed to 'git-rev-list'. Two revision parameters +concatenated with '..' is a short-hand for writing a range +between them. I.e. 'r1..r2' is equivalent to saying '^r1 r2' + + Author ------ Written by Linus Torvalds <torvalds@osdl.org> and @@ -174,7 +174,7 @@ static int loop(void) * the queue because we needed to fetch it first. */ if (! (obj->flags & TO_SCAN)) { - if (fetch(obj->sha1)) { + if (!has_sha1_file(obj->sha1) && fetch(obj->sha1)) { report_missing(obj->type ? obj->type : "object", obj->sha1); diff --git a/git-add.sh b/git-add.sh index 7d91eeb657..3d364db251 100755 --- a/git-add.sh +++ b/git-add.sh @@ -1,2 +1,32 @@ #!/bin/sh -git-update-index --add -- "$@" + +show_only= +verbose= +while : ; do + case "$1" in + -n) + show_only=true + verbose=true + ;; + -v) + verbose=true + ;; + *) + break + ;; + esac + shift +done + +GIT_DIR=$(git-rev-parse --git-dir) || exit +global_exclude= +if [ -f "$GIT_DIR/info/exclude" ]; then + global_exclude="--exclude-from=$GIT_DIR/info/exclude" +fi +for i in $(git-ls-files --others \ + $global_exclude --exclude-per-directory=.gitignore \ + "$@") +do + [ "$verbose" ] && echo " $i" + [ "$show_only" ] || git-update-index --add -- "$i" || exit +done diff --git a/http-fetch.c b/http-fetch.c index 17051fe43a..77f530c95d 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -144,10 +144,11 @@ static int fetch_alternates(char *base) char *url; char *data; int i = 0; + int http_specific = 1; if (got_alternates) return 0; data = xmalloc(4096); - buffer.size = 4096; + buffer.size = 4095; buffer.posn = 0; buffer.buffer = data; @@ -162,6 +163,8 @@ static int fetch_alternates(char *base) curl_easy_setopt(curl, CURLOPT_URL, url); if (curl_easy_perform(curl) || !buffer.posn) { + http_specific = 0; + sprintf(url, "%s/objects/info/alternates", base); curl_easy_setopt(curl, CURLOPT_FILE, &buffer); @@ -173,17 +176,45 @@ static int fetch_alternates(char *base) } } + data[buffer.posn] = '\0'; + while (i < buffer.posn) { int posn = i; while (posn < buffer.posn && data[posn] != '\n') posn++; if (data[posn] == '\n') { + int okay = 0; + int serverlen = 0; + struct alt_base *newalt; + char *target = NULL; if (data[i] == '/') { - int serverlen = strchr(base + 8, '/') - base; - // skip 'objects' at end - char *target = - xmalloc(serverlen + posn - i - 6); - struct alt_base *newalt; + serverlen = strchr(base + 8, '/') - base; + okay = 1; + } else if (!memcmp(data + i, "../", 3)) { + i += 3; + serverlen = strlen(base); + while (i + 2 < posn && + !memcmp(data + i, "../", 3)) { + do { + serverlen--; + } while (serverlen && + base[serverlen - 1] != '/'); + i += 3; + } + // If the server got removed, give up. + okay = strchr(base, ':') - base + 3 < + serverlen; + } else if (http_specific) { + char *colon = strchr(data + i, ':'); + char *slash = strchr(data + i, '/'); + if (colon && slash && colon < data + posn && + slash < data + posn && colon < slash) { + okay = 1; + } + } + // skip 'objects' at end + if (okay) { + target = xmalloc(serverlen + posn - i - 6); strncpy(target, base, serverlen); strncpy(target + serverlen, data + i, posn - i - 7); @@ -235,7 +266,7 @@ static int fetch_indices(struct alt_base *repo) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); if (curl_easy_perform(curl)) { - return error("Unable to get pack index %s", url); + return -1; } while (i < buffer.posn) { diff --git a/rev-parse.c b/rev-parse.c index 6d723f902a..0f5630f95c 100644 --- a/rev-parse.c +++ b/rev-parse.c @@ -191,6 +191,22 @@ int main(int argc, char **argv) puts(prefix); continue; } + if (!strcmp(arg, "--git-dir")) { + const char *gitdir = getenv(GIT_DIR_ENVIRONMENT); + static char cwd[PATH_MAX]; + if (gitdir) { + puts(gitdir); + continue; + } + if (!prefix) { + puts(".git"); + continue; + } + if (!getcwd(cwd, PATH_MAX)) + die("unable to get current working directory"); + printf("%s/.git\n", cwd); + continue; + } if (verify) die("Needed a single revision"); show_flag(arg); diff --git a/update-index.c b/update-index.c index d10dfd9430..8fe015b499 100644 --- a/update-index.c +++ b/update-index.c @@ -50,11 +50,20 @@ static int add_file_to_cache(char *path) * case just fine without --force-remove. */ if (status == 0 || (errno == ENOENT || errno == ENOTDIR)) { - if (allow_remove) - return remove_file_from_cache(path); + if (allow_remove) { + if (remove_file_from_cache(path)) + return error("%s: cannot remove from the index", + path); + else + return 0; + } else if (status < 0) { + return error("%s: does not exist and --remove not passed", + path); + } } if (0 == status) - return error("%s: is a directory", path); + return error("%s: is a directory - add files inside instead", + path); else return error("lstat(\"%s\"): %s", path, strerror(errno)); @@ -71,15 +80,17 @@ static int add_file_to_cache(char *path) case S_IFREG: fd = open(path, O_RDONLY); if (fd < 0) - return -1; + return error("open(\"%s\"): %s", path, strerror(errno)); if (index_fd(ce->sha1, fd, &st, !info_only, NULL) < 0) - return -1; + return error("%s: failed to insert into database", path); break; case S_IFLNK: target = xmalloc(st.st_size+1); if (readlink(path, target, st.st_size+1) != st.st_size) { + char *errstr = strerror(errno); free(target); - return -1; + return error("readlink(\"%s\"): %s", path, + errstr); } if (info_only) { unsigned char hdr[50]; @@ -87,15 +98,18 @@ static int add_file_to_cache(char *path) write_sha1_file_prepare(target, st.st_size, "blob", ce->sha1, hdr, &hdrlen); } else if (write_sha1_file(target, st.st_size, "blob", ce->sha1)) - return -1; + return error("%s: failed to insert into database", path); free(target); break; default: - return -1; + return error("%s: unsupported file type", path); } option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; - return add_cache_entry(ce, option); + if (add_cache_entry(ce, option)) + return error("%s: cannot add to the index - missing --add option?", + path); + return 0; } static int compare_data(struct cache_entry *ce, struct stat *st) @@ -393,11 +407,11 @@ int main(int argc, char **argv) } if (force_remove) { if (remove_file_from_cache(path)) - die("git-update-index: --force-remove cannot remove %s", path); + die("git-update-index: unable to remove %s", path); continue; } if (add_file_to_cache(path)) - die("Unable to add %s to database; maybe you want to use --add option?", path); + die("Unable to process file %s", path); } if (write_cache(newfd, active_cache, active_nr) || commit_index_file(&cache_file)) |