X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=local-fetch.c;h=4bf86fbbe2703514cd3ab39fd9c81accac662aaf;hb=4c5cf8c44ce06a79da5bafd4a92e6d6f598cea2e;hp=a3e35f9c81730ec149bf37cb19d7dbb4570a3197;hpb=1a951815ddaa4e4b570cc67e204f45e9a12841e0;p=git.git diff --git a/local-fetch.c b/local-fetch.c index a3e35f9c8..4bf86fbbe 100644 --- a/local-fetch.c +++ b/local-fetch.c @@ -8,8 +8,9 @@ static int use_link = 0; static int use_symlink = 0; static int use_filecopy = 1; +static int commits_on_stdin = 0; -static char *path; /* "Remote" git repository */ +static const char *path; /* "Remote" git repository */ void prefetch(unsigned char *sha1) { @@ -52,8 +53,10 @@ static int setup_indices(void) return 0; } -static int copy_file(const char *source, const char *dest, const char *hex) +static int copy_file(const char *source, char *dest, const char *hex, + int warn_if_not_exists) { + safe_create_leading_directories(dest); if (use_link) { if (!link(source, dest)) { pull_say("link %s\n", hex); @@ -61,37 +64,43 @@ static int copy_file(const char *source, const char *dest, const char *hex) } /* If we got ENOENT there is no point continuing. */ if (errno == ENOENT) { - fprintf(stderr, "does not exist %s\n", source); + if (warn_if_not_exists) + fprintf(stderr, "does not exist %s\n", source); return -1; } } - if (use_symlink && !symlink(source, dest)) { - pull_say("symlink %s\n", hex); - return 0; + if (use_symlink) { + struct stat st; + if (stat(source, &st)) { + if (!warn_if_not_exists && errno == ENOENT) + return -1; + fprintf(stderr, "cannot stat %s: %s\n", source, + strerror(errno)); + return -1; + } + if (!symlink(source, dest)) { + pull_say("symlink %s\n", hex); + return 0; + } } if (use_filecopy) { - int ifd, ofd, status; - struct stat st; - void *map; + int ifd, ofd, status = 0; + ifd = open(source, O_RDONLY); - if (ifd < 0 || fstat(ifd, &st) < 0) { - if (ifd >= 0) - close(ifd); + if (ifd < 0) { + if (!warn_if_not_exists && errno == ENOENT) + return -1; fprintf(stderr, "cannot open %s\n", source); return -1; } - map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, ifd, 0); - close(ifd); - if (map == MAP_FAILED) { - fprintf(stderr, "cannot mmap %s\n", source); + ofd = open(dest, O_WRONLY | O_CREAT | O_EXCL, 0666); + if (ofd < 0) { + fprintf(stderr, "cannot open %s\n", dest); + close(ifd); return -1; } - ofd = open(dest, O_WRONLY | O_CREAT | O_EXCL, 0666); - status = ((ofd < 0) || - (write(ofd, map, st.st_size) != st.st_size)); - munmap(map, st.st_size); - if (ofd >= 0) - close(ofd); + status = copy_fd(ifd, ofd); + close(ofd); if (status) fprintf(stderr, "cannot write %s\n", dest); else @@ -121,11 +130,11 @@ static int fetch_pack(const unsigned char *sha1) sprintf(filename, "%s/objects/pack/pack-%s.pack", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_name(target->sha1), - sha1_to_hex(target->sha1)); + sha1_to_hex(target->sha1), 1); sprintf(filename, "%s/objects/pack/pack-%s.idx", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_index_name(target->sha1), - sha1_to_hex(target->sha1)); + sha1_to_hex(target->sha1), 1); install_packed_git(target); return 0; } @@ -135,7 +144,7 @@ static int fetch_file(const unsigned char *sha1) static int object_name_start = -1; static char filename[PATH_MAX]; char *hex = sha1_to_hex(sha1); - const char *dest_filename = sha1_file_name(sha1); + char *dest_filename = sha1_file_name(sha1); if (object_name_start < 0) { strcpy(filename, path); /* e.g. git.git */ @@ -146,12 +155,15 @@ static int fetch_file(const unsigned char *sha1) filename[object_name_start+1] = hex[1]; filename[object_name_start+2] = '/'; strcpy(filename + object_name_start + 3, hex + 2); - return copy_file(filename, dest_filename, hex); + return copy_file(filename, dest_filename, hex, 0); } int fetch(unsigned char *sha1) { - return fetch_file(sha1) && fetch_pack(sha1); + if (has_sha1_file(sha1)) + return 0; + else + return fetch_file(sha1) && fetch_pack(sha1); } int fetch_ref(char *ref, unsigned char *sha1) @@ -183,19 +195,25 @@ int fetch_ref(char *ref, unsigned char *sha1) } static const char local_pull_usage[] = -"git-local-fetch [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path"; +"git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] [--stdin] commit-id path"; -/* +/* * By default we only use file copy. * If -l is specified, a hard link is attempted. * If -s is specified, then a symlink is attempted. * If -n is _not_ specified, then a regular file-to-file copy is done. */ -int main(int argc, char **argv) +int main(int argc, const char **argv) { - char *commit_id; + int commits; + const char **write_ref = NULL; + char **commit_id; int arg = 1; + setup_ident(); + setup_git_directory(); + git_config(git_default_config); + while (arg < argc && argv[arg][0] == '-') { if (argv[arg][1] == 't') get_tree = 1; @@ -215,18 +233,30 @@ int main(int argc, char **argv) else if (argv[arg][1] == 'v') get_verbosely = 1; else if (argv[arg][1] == 'w') - write_ref = argv[++arg]; + write_ref = &argv[++arg]; + else if (!strcmp(argv[arg], "--recover")) + get_recover = 1; + else if (!strcmp(argv[arg], "--stdin")) + commits_on_stdin = 1; else usage(local_pull_usage); arg++; } - if (argc < arg + 2) + if (argc < arg + 2 - commits_on_stdin) usage(local_pull_usage); - commit_id = argv[arg]; - path = argv[arg + 1]; + if (commits_on_stdin) { + commits = pull_targets_stdin(&commit_id, &write_ref); + } else { + commit_id = (char **) &argv[arg++]; + commits = 1; + } + path = argv[arg]; - if (pull(commit_id)) + if (pull(commits, commit_id, write_ref, path)) return 1; + if (commits_on_stdin) + pull_targets_free(commits, commit_id, write_ref); + return 0; }