static void read_from_stdin(struct shortlog *log) { struct strbuf author = STRBUF_INIT; struct strbuf mapped_author = STRBUF_INIT; struct strbuf oneline = STRBUF_INIT; static const char *author_match[2] = { "Author: ", "author " }; static const char *committer_match[2] = { "Commit: ", "committer " }; const char **match; match = log->committer ? committer_match : author_match; while (strbuf_getline_lf(&author, stdin) != EOF) { const char *v; if (!skip_prefix(author.buf, match[0], &v) && !skip_prefix(author.buf, match[1], &v)) continue; while (strbuf_getline_lf(&oneline, stdin) != EOF && oneline.len) ; /* discard headers */ while (strbuf_getline_lf(&oneline, stdin) != EOF && !oneline.len) ; /* discard blanks */ strbuf_reset(&mapped_author); if (parse_stdin_author(log, &mapped_author, v) < 0) continue; insert_one_record(log, mapped_author.buf, oneline.buf); } strbuf_release(&author); strbuf_release(&mapped_author); strbuf_release(&oneline); }
static void read_alternate_refs(const char *path, alternate_ref_fn *cb, void *data) { struct child_process cmd = CHILD_PROCESS_INIT; struct strbuf line = STRBUF_INIT; FILE *fh; fill_alternate_refs_command(&cmd, path); if (start_command(&cmd)) return; fh = xfdopen(cmd.out, "r"); while (strbuf_getline_lf(&line, fh) != EOF) { struct object_id oid; const char *p; if (parse_oid_hex(line.buf, &oid, &p) || *p) { warning(_("invalid line while parsing alternate refs: %s"), line.buf); break; } cb(&oid, data); } fclose(fh); finish_command(&cmd); }
static void check_or_regenerate_marks(int latestrev) { FILE *marksfile; struct strbuf sb = STRBUF_INIT; struct strbuf line = STRBUF_INIT; int found = 0; if (latestrev < 1) return; init_notes(NULL, notes_ref, NULL, 0); marksfile = fopen(marksfilename, "r"); if (!marksfile) { regenerate_marks(); marksfile = xfopen(marksfilename, "r"); fclose(marksfile); } else { strbuf_addf(&sb, ":%d ", latestrev); while (strbuf_getline_lf(&line, marksfile) != EOF) { if (starts_with(line.buf, sb.buf)) { found++; break; } } fclose(marksfile); if (!found) regenerate_marks(); } free_notes(NULL); strbuf_release(&sb); strbuf_release(&line); }
static void read_alternate_refs(const char *path, alternate_ref_fn *cb, void *data) { struct child_process cmd = CHILD_PROCESS_INIT; struct strbuf line = STRBUF_INIT; FILE *fh; cmd.git_cmd = 1; argv_array_pushf(&cmd.args, "--git-dir=%s", path); argv_array_push(&cmd.args, "for-each-ref"); argv_array_push(&cmd.args, "--format=%(objectname) %(refname)"); cmd.env = local_repo_env; cmd.out = -1; if (start_command(&cmd)) return; fh = xfdopen(cmd.out, "r"); while (strbuf_getline_lf(&line, fh) != EOF) { struct object_id oid; if (get_oid_hex(line.buf, &oid) || line.buf[GIT_SHA1_HEXSZ] != ' ') { warning("invalid line while parsing alternate refs: %s", line.buf); break; } cb(line.buf + GIT_SHA1_HEXSZ + 1, &oid, data); } fclose(fh); finish_command(&cmd); }
static void parse_push(struct strbuf *buf) { char **specs = NULL; int alloc_spec = 0, nr_spec = 0, i, ret; do { if (starts_with(buf->buf, "push ")) { ALLOC_GROW(specs, nr_spec + 1, alloc_spec); specs[nr_spec++] = xstrdup(buf->buf + 5); } else die("http transport does not support %s", buf->buf); strbuf_reset(buf); if (strbuf_getline_lf(buf, stdin) == EOF) goto free_specs; if (!*buf->buf) break; } while (1); ret = push(nr_spec, specs); printf("\n"); fflush(stdout); if (ret) exit(128); /* error already reported */ free_specs: for (i = 0; i < nr_spec; i++) free(specs[i]); free(specs); }
int main(int argc, char **argv) { struct sha1_array array = SHA1_ARRAY_INIT; struct strbuf line = STRBUF_INIT; while (strbuf_getline_lf(&line, stdin) != EOF) { const char *arg; unsigned char sha1[20]; if (skip_prefix(line.buf, "append ", &arg)) { if (get_sha1_hex(arg, sha1)) die("not a hexadecimal SHA1: %s", arg); sha1_array_append(&array, sha1); } else if (skip_prefix(line.buf, "lookup ", &arg)) { if (get_sha1_hex(arg, sha1)) die("not a hexadecimal SHA1: %s", arg); printf("%d\n", sha1_array_lookup(&array, sha1)); } else if (!strcmp(line.buf, "clear")) sha1_array_clear(&array); else if (!strcmp(line.buf, "for_each_unique")) sha1_array_for_each_unique(&array, print_sha1, NULL); else die("unknown command: %s", line.buf); } return 0; }
int cmd_check_mailmap(int argc, const char **argv, const char *prefix) { int i; struct string_list mailmap = STRING_LIST_INIT_NODUP; git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, check_mailmap_options, check_mailmap_usage, 0); if (argc == 0 && !use_stdin) die(_("no contacts specified")); read_mailmap(&mailmap, NULL); for (i = 0; i < argc; ++i) check_mailmap(&mailmap, argv[i]); maybe_flush_or_die(stdout, "stdout"); if (use_stdin) { struct strbuf buf = STRBUF_INIT; while (strbuf_getline_lf(&buf, stdin) != EOF) { check_mailmap(&mailmap, buf.buf); maybe_flush_or_die(stdout, "stdout"); } strbuf_release(&buf); } clear_mailmap(&mailmap); return 0; }
static int find_boundary(struct mailinfo *mi, struct strbuf *line) { while (!strbuf_getline_lf(line, mi->input)) { if (*(mi->content_top) && is_multipart_boundary(mi, line)) return 1; } return 0; }
static int notes_copy_from_stdin(int force, const char *rewrite_cmd) { struct strbuf buf = STRBUF_INIT; struct notes_rewrite_cfg *c = NULL; struct notes_tree *t = NULL; int ret = 0; const char *msg = "Notes added by 'git notes copy'"; if (rewrite_cmd) { c = init_copy_notes_for_rewrite(rewrite_cmd); if (!c) return 0; } else { init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE); t = &default_notes_tree; } while (strbuf_getline_lf(&buf, stdin) != EOF) { struct object_id from_obj, to_obj; struct strbuf **split; int err; split = strbuf_split(&buf, ' '); if (!split[0] || !split[1]) die(_("malformed input line: '%s'."), buf.buf); strbuf_rtrim(split[0]); strbuf_rtrim(split[1]); if (get_oid(split[0]->buf, &from_obj)) die(_("failed to resolve '%s' as a valid ref."), split[0]->buf); if (get_oid(split[1]->buf, &to_obj)) die(_("failed to resolve '%s' as a valid ref."), split[1]->buf); if (rewrite_cmd) err = copy_note_for_rewrite(c, &from_obj, &to_obj); else err = copy_note(t, &from_obj, &to_obj, force, combine_notes_overwrite); if (err) { error(_("failed to copy notes from '%s' to '%s'"), split[0]->buf, split[1]->buf); ret = 1; } strbuf_list_free(split); } if (!rewrite_cmd) { commit_notes(t, msg); free_notes(t); } else { finish_copy_notes_for_rewrite(c, msg); } strbuf_release(&buf); return ret; }
static int read_request(FILE *fh, struct credential *c, struct strbuf *action, int *timeout) { static struct strbuf item = STRBUF_INIT; const char *p; strbuf_getline_lf(&item, fh); if (!skip_prefix(item.buf, "action=", &p)) return error("client sent bogus action line: %s", item.buf); strbuf_addstr(action, p); strbuf_getline_lf(&item, fh); if (!skip_prefix(item.buf, "timeout=", &p)) return error("client sent bogus timeout line: %s", item.buf); *timeout = atoi(p); if (credential_read(c, fh) < 0) return -1; return 0; }
int cmd_main(int argc, const char **argv) { struct strbuf buf = STRBUF_INIT, url_sb = STRBUF_INIT, private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT, notes_ref_sb = STRBUF_INIT; static struct remote *remote; const char *url_in; setup_git_directory(); if (argc < 2 || argc > 3) { usage("git-remote-svn <remote-name> [<url>]"); return 1; } remote = remote_get(argv[1]); url_in = (argc == 3) ? argv[2] : remote->url[0]; if (starts_with(url_in, "file://")) { dump_from_file = 1; url = url_decode(url_in + sizeof("file://")-1); } else { dump_from_file = 0; end_url_with_slash(&url_sb, url_in); url = url_sb.buf; } strbuf_addf(&private_ref_sb, "refs/svn/%s/master", remote->name); private_ref = private_ref_sb.buf; strbuf_addf(¬es_ref_sb, "refs/notes/%s/revs", remote->name); notes_ref = notes_ref_sb.buf; strbuf_addf(&marksfilename_sb, "%s/info/fast-import/remote-svn/%s.marks", get_git_dir(), remote->name); marksfilename = marksfilename_sb.buf; while (1) { if (strbuf_getline_lf(&buf, stdin) == EOF) { if (ferror(stdin)) die("Error reading command stream"); else die("Unexpected end of command stream"); } if (do_command(&buf)) break; strbuf_reset(&buf); } strbuf_release(&buf); strbuf_release(&url_sb); strbuf_release(&private_ref_sb); strbuf_release(¬es_ref_sb); strbuf_release(&marksfilename_sb); return 0; }
static int read_one_header_line(struct strbuf *line, FILE *in) { struct strbuf continuation = STRBUF_INIT; /* Get the first part of the line. */ if (strbuf_getline_lf(line, in)) return 0; /* * Is it an empty line or not a valid rfc2822 header? * If so, stop here, and return false ("not a header") */ strbuf_rtrim(line); if (!line->len || !is_rfc2822_header(line)) { /* Re-add the newline */ strbuf_addch(line, '\n'); return 0; } /* * Now we need to eat all the continuation lines.. * Yuck, 2822 header "folding" */ for (;;) { int peek; peek = fgetc(in); if (peek == EOF) break; ungetc(peek, in); if (peek != ' ' && peek != '\t') break; if (strbuf_getline_lf(&continuation, in)) break; continuation.buf[0] = ' '; strbuf_rtrim(&continuation); strbuf_addbuf(line, &continuation); } strbuf_release(&continuation); return 1; }
static void parse_fetch(struct strbuf *buf) { struct ref **to_fetch = NULL; struct ref *list_head = NULL; struct ref **list = &list_head; int alloc_heads = 0, nr_heads = 0; do { const char *p; if (skip_prefix(buf->buf, "fetch ", &p)) { const char *name; struct ref *ref; struct object_id old_oid; if (get_oid_hex(p, &old_oid)) die("protocol error: expected sha/ref, got %s'", p); if (p[GIT_SHA1_HEXSZ] == ' ') name = p + GIT_SHA1_HEXSZ + 1; else if (!p[GIT_SHA1_HEXSZ]) name = ""; else die("protocol error: expected sha/ref, got %s'", p); ref = alloc_ref(name); oidcpy(&ref->old_oid, &old_oid); *list = ref; list = &ref->next; ALLOC_GROW(to_fetch, nr_heads + 1, alloc_heads); to_fetch[nr_heads++] = ref; } else die("http transport does not support %s", buf->buf); strbuf_reset(buf); if (strbuf_getline_lf(buf, stdin) == EOF) return; if (!*buf->buf) break; } while (1); if (fetch(nr_heads, to_fetch)) exit(128); /* error already reported */ free_refs(list_head); free(to_fetch); printf("\n"); fflush(stdout); strbuf_reset(buf); }
/* * The terms used for this bisect session are stored in BISECT_TERMS. * We read them and store them to adapt the messages accordingly. * Default is bad/good. */ void read_bisect_terms(const char **read_bad, const char **read_good) { struct strbuf str = STRBUF_INIT; const char *filename = git_path("BISECT_TERMS"); FILE *fp = fopen(filename, "r"); if (!fp) { if (errno == ENOENT) { *read_bad = "bad"; *read_good = "good"; return; } else { die_errno("could not read file '%s'", filename); } } else { strbuf_getline_lf(&str, fp); *read_bad = strbuf_detach(&str, NULL); strbuf_getline_lf(&str, fp); *read_good = strbuf_detach(&str, NULL); } strbuf_release(&str); fclose(fp); }
char *git_terminal_prompt(const char *prompt, int echo) { static struct strbuf buf = STRBUF_INIT; int r; FILE *input_fh, *output_fh; #ifdef GIT_WINDOWS_NATIVE /* try shell_prompt first, fall back to CONIN/OUT if bash is missing */ char *result = shell_prompt(prompt, echo); if (result) return result; if (echo && set_echo(1)) return NULL; #endif input_fh = fopen(INPUT_PATH, "r" FORCE_TEXT); if (!input_fh) return NULL; output_fh = fopen(OUTPUT_PATH, "w" FORCE_TEXT); if (!output_fh) { fclose(input_fh); return NULL; } if (!echo && disable_echo()) { fclose(input_fh); fclose(output_fh); return NULL; } fputs(prompt, output_fh); fflush(output_fh); r = strbuf_getline_lf(&buf, input_fh); if (!echo) { putc('\n', output_fh); fflush(output_fh); } restore_term(); fclose(input_fh); fclose(output_fh); if (r == EOF) return NULL; return buf.buf; }
static int handle_boundary(struct mailinfo *mi, struct strbuf *line) { struct strbuf newline = STRBUF_INIT; strbuf_addch(&newline, '\n'); again: if (line->len >= (*(mi->content_top))->len + 2 && !memcmp(line->buf + (*(mi->content_top))->len, "--", 2)) { /* we hit an end boundary */ /* pop the current boundary off the stack */ strbuf_release(*(mi->content_top)); free(*(mi->content_top)); *(mi->content_top) = NULL; /* technically won't happen as is_multipart_boundary() will fail first. But just in case.. */ if (--mi->content_top < mi->content) { error("Detected mismatched boundaries, can't recover"); mi->input_error = -1; mi->content_top = mi->content; return 0; } handle_filter(mi, &newline); strbuf_release(&newline); if (mi->input_error) return 0; /* skip to the next boundary */ if (!find_boundary(mi, line)) return 0; goto again; } /* set some defaults */ mi->transfer_encoding = TE_DONTCARE; strbuf_reset(&mi->charset); /* slurp in this section's info */ while (read_one_header_line(line, mi->input)) check_header(mi, line, mi->p_hdr_data, 0); strbuf_release(&newline); /* replenish line */ if (strbuf_getline_lf(line, mi->input)) return 0; strbuf_addch(line, '\n'); return 1; }
static int get_terms(struct bisect_terms *terms) { struct strbuf str = STRBUF_INIT; FILE *fp = NULL; int res = 0; fp = fopen(git_path_bisect_terms(), "r"); if (!fp) { res = -1; goto finish; } free_terms(terms); strbuf_getline_lf(&str, fp); terms->term_bad = strbuf_detach(&str, NULL); strbuf_getline_lf(&str, fp); terms->term_good = strbuf_detach(&str, NULL); finish: if (fp) fclose(fp); strbuf_release(&str); return res; }
int credential_read(struct credential *c, FILE *fp) { struct strbuf line = STRBUF_INIT; while (strbuf_getline_lf(&line, fp) != EOF) { char *key = line.buf; char *value = strchr(key, '='); if (!line.len) break; if (!value) { warning("invalid credential line: %s", key); strbuf_release(&line); return -1; } *value++ = '\0'; if (!strcmp(key, "username")) { free(c->username); c->username = xstrdup(value); } else if (!strcmp(key, "password")) { free(c->password); c->password = xstrdup(value); } else if (!strcmp(key, "protocol")) { free(c->protocol); c->protocol = xstrdup(value); } else if (!strcmp(key, "host")) { free(c->host); c->host = xstrdup(value); } else if (!strcmp(key, "path")) { free(c->path); c->path = xstrdup(value); } else if (!strcmp(key, "url")) { credential_from_url(c, value); } else if (!strcmp(key, "quit")) { c->quit = !!git_config_bool("quit", value); } /* * Ignore other lines; we don't know what they mean, but * this future-proofs us when later versions of git do * learn new lines, and the helpers are updated to match. */ } strbuf_release(&line); return 0; }
int sequencer_rollback(struct replay_opts *opts) { FILE *f; unsigned char sha1[20]; struct strbuf buf = STRBUF_INIT; f = fopen(git_path_head_file(), "r"); if (!f && errno == ENOENT) { /* * There is no multiple-cherry-pick in progress. * If CHERRY_PICK_HEAD or REVERT_HEAD indicates * a single-cherry-pick in progress, abort that. */ return rollback_single_pick(); } if (!f) return error_errno(_("cannot open '%s'"), git_path_head_file()); if (strbuf_getline_lf(&buf, f)) { error(_("cannot read '%s': %s"), git_path_head_file(), ferror(f) ? strerror(errno) : _("unexpected end of file")); fclose(f); goto fail; } fclose(f); if (get_sha1_hex(buf.buf, sha1) || buf.buf[40] != '\0') { error(_("stored pre-cherry-pick HEAD file '%s' is corrupt"), git_path_head_file()); goto fail; } if (is_null_sha1(sha1)) { error(_("cannot abort from a branch yet to be born")); goto fail; } if (!rollback_is_safe()) { /* Do not error, just do not rollback */ warning(_("You seem to have moved HEAD. " "Not rewinding, check your HEAD!")); } else if (reset_for_rollback(sha1)) goto fail; strbuf_release(&buf); return sequencer_remove_state(opts); fail: strbuf_release(&buf); return -1; }
static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, int literally) { struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; while (strbuf_getline_lf(&buf, stdin) != EOF) { if (buf.buf[0] == '"') { strbuf_reset(&nbuf); if (unquote_c_style(&nbuf, buf.buf, NULL)) die("line is badly quoted"); strbuf_swap(&buf, &nbuf); } hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags, literally); } strbuf_release(&buf); strbuf_release(&nbuf); }
/** * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge * into merge_heads. */ static void get_merge_heads(struct oid_array *merge_heads) { const char *filename = git_path_fetch_head(the_repository); FILE *fp; struct strbuf sb = STRBUF_INIT; struct object_id oid; fp = xfopen(filename, "r"); while (strbuf_getline_lf(&sb, fp) != EOF) { if (get_oid_hex(sb.buf, &oid)) continue; /* invalid line: does not start with SHA1 */ if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t")) continue; /* ref is not-for-merge */ oid_array_append(merge_heads, &oid); } fclose(fp); strbuf_release(&sb); }
/** * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge * into merge_heads. */ static void get_merge_heads(struct sha1_array *merge_heads) { const char *filename = git_path("FETCH_HEAD"); FILE *fp; struct strbuf sb = STRBUF_INIT; unsigned char sha1[GIT_SHA1_RAWSZ]; if (!(fp = fopen(filename, "r"))) die_errno(_("could not open '%s' for reading"), filename); while (strbuf_getline_lf(&sb, fp) != EOF) { if (get_sha1_hex(sb.buf, sha1)) continue; /* invalid line: does not start with SHA1 */ if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t")) continue; /* ref is not-for-merge */ sha1_array_append(merge_heads, sha1); } fclose(fp); strbuf_release(&sb); }
static void read_bisect_paths(struct argv_array *array) { struct strbuf str = STRBUF_INIT; const char *filename = git_path_bisect_names(); FILE *fp = fopen(filename, "r"); if (!fp) die_errno("Could not open file '%s'", filename); while (strbuf_getline_lf(&str, fp) != EOF) { strbuf_trim(&str); if (sq_dequote_to_argv_array(str.buf, array)) die("Badly quoted content in file '%s': %s", filename, str.buf); } strbuf_release(&str); fclose(fp); }
static void copy_to_log(int fd) { struct strbuf line = STRBUF_INIT; FILE *fp; fp = fdopen(fd, "r"); if (fp == NULL) { logerror("fdopen of error channel failed"); close(fd); return; } while (strbuf_getline_lf(&line, fp) != EOF) { logerror("%s", line.buf); strbuf_setlen(&line, 0); } strbuf_release(&line); fclose(fp); }
static int is_expected_rev(const struct object_id *oid) { const char *filename = git_path_bisect_expected_rev(); struct stat st; struct strbuf str = STRBUF_INIT; FILE *fp; int res = 0; if (stat(filename, &st) || !S_ISREG(st.st_mode)) return 0; fp = fopen(filename, "r"); if (!fp) return 0; if (strbuf_getline_lf(&str, fp) != EOF) res = !strcmp(str.buf, oid_to_hex(oid)); strbuf_release(&str); fclose(fp); return res; }
static int parse_credential_file(const char *fn, struct credential *c, void (*match_cb)(struct credential *), void (*other_cb)(struct strbuf *)) { FILE *fh; struct strbuf line = STRBUF_INIT; struct credential entry = CREDENTIAL_INIT; int found_credential = 0; fh = fopen(fn, "r"); if (!fh) { if (errno != ENOENT && errno != EACCES) die_errno("unable to open %s", fn); return found_credential; } while (strbuf_getline_lf(&line, fh) != EOF) { credential_from_url(&entry, line.buf); if (entry.username && entry.password && credential_match(c, &entry)) { found_credential = 1; if (match_cb) { match_cb(&entry); break; } } else if (other_cb) other_cb(&line); } credential_clear(&entry); strbuf_release(&line); fclose(fh); return found_credential; }
static void run_shell(void) { int done = 0; static const char *help_argv[] = { HELP_COMMAND, NULL }; if (!access(NOLOGIN_COMMAND, F_OK)) { /* Interactive login disabled. */ const char *argv[] = { NOLOGIN_COMMAND, NULL }; int status; status = run_command_v_opt(argv, 0); if (status < 0) exit(127); exit(status); } /* Print help if enabled */ run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE); do { struct strbuf line = STRBUF_INIT; const char *prog; char *full_cmd; char *rawargs; char *split_args; const char **argv; int code; int count; fprintf(stderr, "git> "); if (strbuf_getline_lf(&line, stdin) == EOF) { fprintf(stderr, "\n"); strbuf_release(&line); break; } strbuf_trim(&line); rawargs = strbuf_detach(&line, NULL); split_args = xstrdup(rawargs); count = split_cmdline(split_args, &argv); if (count < 0) { fprintf(stderr, "invalid command format '%s': %s\n", rawargs, split_cmdline_strerror(count)); free(split_args); free(rawargs); continue; } prog = argv[0]; if (!strcmp(prog, "")) { } else if (!strcmp(prog, "quit") || !strcmp(prog, "logout") || !strcmp(prog, "exit") || !strcmp(prog, "bye")) { done = 1; } else if (is_valid_cmd_name(prog)) { full_cmd = make_cmd(prog); argv[0] = full_cmd; code = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE); if (code == -1 && errno == ENOENT) { fprintf(stderr, "unrecognized command '%s'\n", prog); } free(full_cmd); } else { fprintf(stderr, "invalid command format '%s'\n", prog); } free(argv); free(rawargs); } while (!done); }
int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret; struct ref *ref = NULL; const char *dest = NULL; struct ref **sought = NULL; int nr_sought = 0, alloc_sought = 0; int fd[2]; char *pack_lockfile = NULL; char **pack_lockfile_ptr = NULL; struct child_process *conn; struct fetch_pack_args args; struct oid_array shallow = OID_ARRAY_INIT; struct string_list deepen_not = STRING_LIST_INIT_DUP; struct packet_reader reader; enum protocol_version version; fetch_if_missing = 0; packet_trace_identity("fetch-pack"); memset(&args, 0, sizeof(args)); args.uploadpack = "git-upload-pack"; for (i = 1; i < argc && *argv[i] == '-'; i++) { const char *arg = argv[i]; if (skip_prefix(arg, "--upload-pack=", &arg)) { args.uploadpack = arg; continue; } if (skip_prefix(arg, "--exec=", &arg)) { args.uploadpack = arg; continue; } if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) { args.quiet = 1; continue; } if (!strcmp("--keep", arg) || !strcmp("-k", arg)) { args.lock_pack = args.keep_pack; args.keep_pack = 1; continue; } if (!strcmp("--thin", arg)) { args.use_thin_pack = 1; continue; } if (!strcmp("--include-tag", arg)) { args.include_tag = 1; continue; } if (!strcmp("--all", arg)) { args.fetch_all = 1; continue; } if (!strcmp("--stdin", arg)) { args.stdin_refs = 1; continue; } if (!strcmp("--diag-url", arg)) { args.diag_url = 1; continue; } if (!strcmp("-v", arg)) { args.verbose = 1; continue; } if (skip_prefix(arg, "--depth=", &arg)) { args.depth = strtol(arg, NULL, 0); continue; } if (skip_prefix(arg, "--shallow-since=", &arg)) { args.deepen_since = xstrdup(arg); continue; } if (skip_prefix(arg, "--shallow-exclude=", &arg)) { string_list_append(&deepen_not, arg); continue; } if (!strcmp(arg, "--deepen-relative")) { args.deepen_relative = 1; continue; } if (!strcmp("--no-progress", arg)) { args.no_progress = 1; continue; } if (!strcmp("--stateless-rpc", arg)) { args.stateless_rpc = 1; continue; } if (!strcmp("--lock-pack", arg)) { args.lock_pack = 1; pack_lockfile_ptr = &pack_lockfile; continue; } if (!strcmp("--check-self-contained-and-connected", arg)) { args.check_self_contained_and_connected = 1; continue; } if (!strcmp("--cloning", arg)) { args.cloning = 1; continue; } if (!strcmp("--update-shallow", arg)) { args.update_shallow = 1; continue; } if (!strcmp("--from-promisor", arg)) { args.from_promisor = 1; continue; } if (!strcmp("--no-dependents", arg)) { args.no_dependents = 1; continue; } if (skip_prefix(arg, ("--" CL_ARG__FILTER "="), &arg)) { parse_list_objects_filter(&args.filter_options, arg); continue; } if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) { list_objects_filter_set_no_filter(&args.filter_options); continue; } usage(fetch_pack_usage); } if (deepen_not.nr) args.deepen_not = &deepen_not; if (i < argc) dest = argv[i++]; else usage(fetch_pack_usage); /* * Copy refs from cmdline to growable list, then append any * refs from the standard input: */ for (; i < argc; i++) add_sought_entry(&sought, &nr_sought, &alloc_sought, argv[i]); if (args.stdin_refs) { if (args.stateless_rpc) { /* in stateless RPC mode we use pkt-line to read * from stdin, until we get a flush packet */ for (;;) { char *line = packet_read_line(0, NULL); if (!line) break; add_sought_entry(&sought, &nr_sought, &alloc_sought, line); } } else { /* read from stdin one ref per line, until EOF */ struct strbuf line = STRBUF_INIT; while (strbuf_getline_lf(&line, stdin) != EOF) add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf); strbuf_release(&line); } } if (args.stateless_rpc) { conn = NULL; fd[0] = 0; fd[1] = 1; } else { int flags = args.verbose ? CONNECT_VERBOSE : 0; if (args.diag_url) flags |= CONNECT_DIAG_URL; conn = git_connect(fd, dest, args.uploadpack, flags); if (!conn) return args.diag_url ? 0 : 1; } packet_reader_init(&reader, fd[0], NULL, 0, PACKET_READ_CHOMP_NEWLINE | PACKET_READ_GENTLE_ON_EOF | PACKET_READ_DIE_ON_ERR_PACKET); version = discover_version(&reader); switch (version) { case protocol_v2: get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL); break; case protocol_v1: case protocol_v0: get_remote_heads(&reader, &ref, 0, NULL, &shallow); break; case protocol_unknown_version: BUG("unknown protocol version"); } ref = fetch_pack(&args, fd, conn, ref, dest, sought, nr_sought, &shallow, pack_lockfile_ptr, version); if (pack_lockfile) { printf("lock %s\n", pack_lockfile); fflush(stdout); } if (args.check_self_contained_and_connected && args.self_contained_and_connected) { printf("connectivity-ok\n"); fflush(stdout); } close(fd[0]); close(fd[1]); if (finish_connect(conn)) return 1; ret = !ref; /* * If the heads to pull were given, we should have consumed * all of them by matching the remote. Otherwise, 'git fetch * remote no-such-ref' would silently succeed without issuing * an error. */ ret |= report_unmatched_refs(sought, nr_sought); while (ref) { printf("%s %s\n", oid_to_hex(&ref->old_oid), ref->name); ref = ref->next; } return ret; }
int main(int argc, const char **argv) { struct strbuf buf = STRBUF_INIT; int nongit; git_setup_gettext(); git_extract_argv0_path(argv[0]); setup_git_directory_gently(&nongit); if (argc < 2) { error("remote-curl: usage: git remote-curl <remote> [<url>]"); return 1; } options.verbosity = 1; options.progress = !!isatty(2); options.thin = 1; remote = remote_get(argv[1]); if (argc > 2) { end_url_with_slash(&url, argv[2]); } else { end_url_with_slash(&url, remote->url[0]); } http_init(remote, url.buf, 0); do { const char *arg; if (strbuf_getline_lf(&buf, stdin) == EOF) { if (ferror(stdin)) error("remote-curl: error reading command stream from git"); return 1; } if (buf.len == 0) break; if (starts_with(buf.buf, "fetch ")) { if (nongit) die("remote-curl: fetch attempted without a local repo"); parse_fetch(&buf); } else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) { int for_push = !!strstr(buf.buf + 4, "for-push"); output_refs(get_refs(for_push)); } else if (starts_with(buf.buf, "push ")) { parse_push(&buf); } else if (skip_prefix(buf.buf, "option ", &arg)) { char *value = strchr(arg, ' '); int result; if (value) *value++ = '\0'; else value = "true"; result = set_option(arg, value); if (!result) printf("ok\n"); else if (result < 0) printf("error invalid value\n"); else printf("unsupported\n"); fflush(stdout); } else if (!strcmp(buf.buf, "capabilities")) { printf("fetch\n"); printf("option\n"); printf("push\n"); printf("check-connectivity\n"); printf("\n"); fflush(stdout); } else { error("remote-curl: unknown command '%s' from git", buf.buf); return 1; } strbuf_reset(&buf); } while (1); http_cleanup(); return 0; }