int dwim_log(const char *str, int len, unsigned char *sha1, char **log) { char *last_branch = substitute_branch_name(&str, &len); const char **p; int logs_found = 0; *log = NULL; for (p = ref_rev_parse_rules; *p; p++) { unsigned char hash[20]; char path[PATH_MAX]; const char *ref, *it; mksnpath(path, sizeof(path), *p, len, str); ref = resolve_ref_unsafe(path, RESOLVE_REF_READING, hash, NULL); if (!ref) continue; if (reflog_exists(path)) it = path; else if (strcmp(ref, path) && reflog_exists(ref)) it = ref; else continue; if (!logs_found++) { *log = xstrdup(it); hashcpy(sha1, hash); } if (!warn_ambiguous_refs) break; } free(last_branch); return logs_found; }
int dwim_log(const char *str, int len, unsigned char *sha1, char **log) { char *last_branch = substitute_branch_name(&str, &len); const char **p; int logs_found = 0; struct strbuf path = STRBUF_INIT; *log = NULL; for (p = ref_rev_parse_rules; *p; p++) { unsigned char hash[20]; const char *ref, *it; strbuf_reset(&path); strbuf_addf(&path, *p, len, str); ref = resolve_ref_unsafe(path.buf, RESOLVE_REF_READING, hash, NULL); if (!ref) continue; if (reflog_exists(path.buf)) it = path.buf; else if (strcmp(ref, path.buf) && reflog_exists(ref)) it = ref; else continue; if (!logs_found++) { *log = xstrdup(it); hashcpy(sha1, hash); } if (!warn_ambiguous_refs) break; } strbuf_release(&path); free(last_branch); return logs_found; }
static int cmd_reflog_exists(int argc, const char **argv, const char *prefix) { int i, start = 0; for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--")) { i++; break; } else if (arg[0] == '-') usage(_(reflog_exists_usage)); else break; } start = i; if (argc - start != 1) usage(_(reflog_exists_usage)); if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL)) die(_("invalid ref format: %s"), argv[start]); return !reflog_exists(argv[start]); }
static int do_push_stash(struct pathspec ps, const char *stash_msg, int quiet, int keep_index, int patch_mode, int include_untracked) { int ret = 0; struct stash_info info; struct strbuf patch = STRBUF_INIT; struct strbuf stash_msg_buf = STRBUF_INIT; struct strbuf untracked_files = STRBUF_INIT; if (patch_mode && keep_index == -1) keep_index = 1; if (patch_mode && include_untracked) { fprintf_ln(stderr, _("Can't use --patch and --include-untracked" " or --all at the same time")); ret = -1; goto done; } read_cache_preload(NULL); if (!include_untracked && ps.nr) { int i; char *ps_matched = xcalloc(ps.nr, 1); for (i = 0; i < active_nr; i++) ce_path_match(&the_index, active_cache[i], &ps, ps_matched); if (report_path_error(ps_matched, &ps, NULL)) { fprintf_ln(stderr, _("Did you forget to 'git add'?")); ret = -1; free(ps_matched); goto done; } free(ps_matched); } if (refresh_cache(REFRESH_QUIET)) { ret = -1; goto done; } if (!check_changes(ps, include_untracked, &untracked_files)) { if (!quiet) printf_ln(_("No local changes to save")); goto done; } if (!reflog_exists(ref_stash) && do_clear_stash()) { ret = -1; if (!quiet) fprintf_ln(stderr, _("Cannot initialize stash")); goto done; } if (stash_msg) strbuf_addstr(&stash_msg_buf, stash_msg); if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode, &info, &patch, quiet)) { ret = -1; goto done; } if (do_store_stash(&info.w_commit, stash_msg_buf.buf, 1)) { ret = -1; if (!quiet) fprintf_ln(stderr, _("Cannot save the current status")); goto done; } if (!quiet) printf_ln(_("Saved working directory and index state %s"), stash_msg_buf.buf); if (!patch_mode) { if (include_untracked && !ps.nr) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "clean", "--force", "--quiet", "-d", NULL); if (include_untracked == INCLUDE_ALL_FILES) argv_array_push(&cp.args, "-x"); if (run_command(&cp)) { ret = -1; goto done; } } discard_cache(); if (ps.nr) { struct child_process cp_add = CHILD_PROCESS_INIT; struct child_process cp_diff = CHILD_PROCESS_INIT; struct child_process cp_apply = CHILD_PROCESS_INIT; struct strbuf out = STRBUF_INIT; cp_add.git_cmd = 1; argv_array_push(&cp_add.args, "add"); if (!include_untracked) argv_array_push(&cp_add.args, "-u"); if (include_untracked == INCLUDE_ALL_FILES) argv_array_push(&cp_add.args, "--force"); argv_array_push(&cp_add.args, "--"); add_pathspecs(&cp_add.args, ps); if (run_command(&cp_add)) { ret = -1; goto done; } cp_diff.git_cmd = 1; argv_array_pushl(&cp_diff.args, "diff-index", "-p", "--cached", "--binary", "HEAD", "--", NULL); add_pathspecs(&cp_diff.args, ps); if (pipe_command(&cp_diff, NULL, 0, &out, 0, NULL, 0)) { ret = -1; goto done; } cp_apply.git_cmd = 1; argv_array_pushl(&cp_apply.args, "apply", "--index", "-R", NULL); if (pipe_command(&cp_apply, out.buf, out.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } } else { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "reset", "--hard", "-q", NULL); if (run_command(&cp)) { ret = -1; goto done; } } if (keep_index == 1 && !is_null_oid(&info.i_tree)) { struct child_process cp_ls = CHILD_PROCESS_INIT; struct child_process cp_checkout = CHILD_PROCESS_INIT; struct strbuf out = STRBUF_INIT; if (reset_tree(&info.i_tree, 0, 1)) { ret = -1; goto done; } cp_ls.git_cmd = 1; argv_array_pushl(&cp_ls.args, "ls-files", "-z", "--modified", "--", NULL); add_pathspecs(&cp_ls.args, ps); if (pipe_command(&cp_ls, NULL, 0, &out, 0, NULL, 0)) { ret = -1; goto done; } cp_checkout.git_cmd = 1; argv_array_pushl(&cp_checkout.args, "checkout-index", "-z", "--force", "--stdin", NULL); if (pipe_command(&cp_checkout, out.buf, out.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } } goto done; } else { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "apply", "-R", NULL); if (pipe_command(&cp, patch.buf, patch.len, NULL, 0, NULL, 0)) { if (!quiet) fprintf_ln(stderr, _("Cannot remove " "worktree changes")); ret = -1; goto done; } if (keep_index < 1) { struct child_process cp = CHILD_PROCESS_INIT; discard_cache(); cp.git_cmd = 1; argv_array_pushl(&cp.args, "reset", "-q", "--", NULL); add_pathspecs(&cp.args, ps); if (run_command(&cp)) { ret = -1; goto done; } } goto done; } done: strbuf_release(&stash_msg_buf); return ret; }
static void update_refs_for_switch(const struct checkout_opts *opts, struct branch_info *old_branch_info, struct branch_info *new_branch_info) { struct strbuf msg = STRBUF_INIT; const char *old_desc, *reflog_msg; if (opts->new_branch) { if (opts->new_orphan_branch) { char *refname; refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch); if (opts->new_branch_log && !should_autocreate_reflog(refname)) { int ret; struct strbuf err = STRBUF_INIT; ret = safe_create_reflog(refname, 1, &err); if (ret) { fprintf(stderr, _("Can not do reflog for '%s': %s\n"), opts->new_orphan_branch, err.buf); strbuf_release(&err); free(refname); return; } strbuf_release(&err); } free(refname); } else create_branch(the_repository, opts->new_branch, new_branch_info->name, opts->new_branch_force ? 1 : 0, opts->new_branch_force ? 1 : 0, opts->new_branch_log, opts->quiet, opts->track); new_branch_info->name = opts->new_branch; setup_branch_path(new_branch_info); } old_desc = old_branch_info->name; if (!old_desc && old_branch_info->commit) old_desc = oid_to_hex(&old_branch_info->commit->object.oid); reflog_msg = getenv("GIT_REFLOG_ACTION"); if (!reflog_msg) strbuf_addf(&msg, "checkout: moving from %s to %s", old_desc ? old_desc : "(invalid)", new_branch_info->name); else strbuf_insert(&msg, 0, reflog_msg, strlen(reflog_msg)); if (!strcmp(new_branch_info->name, "HEAD") && !new_branch_info->path && !opts->force_detach) { /* Nothing to do. */ } else if (opts->force_detach || !new_branch_info->path) { /* No longer on any branch. */ update_ref(msg.buf, "HEAD", &new_branch_info->commit->object.oid, NULL, REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR); if (!opts->quiet) { if (old_branch_info->path && advice_detached_head && !opts->force_detach) detach_advice(new_branch_info->name); describe_detached_head(_("HEAD is now at"), new_branch_info->commit); } } else if (new_branch_info->path) { /* Switch branches. */ if (create_symref("HEAD", new_branch_info->path, msg.buf) < 0) die(_("unable to update HEAD")); if (!opts->quiet) { if (old_branch_info->path && !strcmp(new_branch_info->path, old_branch_info->path)) { if (opts->new_branch_force) fprintf(stderr, _("Reset branch '%s'\n"), new_branch_info->name); else fprintf(stderr, _("Already on '%s'\n"), new_branch_info->name); } else if (opts->new_branch) { if (opts->branch_exists) fprintf(stderr, _("Switched to and reset branch '%s'\n"), new_branch_info->name); else fprintf(stderr, _("Switched to a new branch '%s'\n"), new_branch_info->name); } else { fprintf(stderr, _("Switched to branch '%s'\n"), new_branch_info->name); } } if (old_branch_info->path && old_branch_info->name) { if (!ref_exists(old_branch_info->path) && reflog_exists(old_branch_info->path)) delete_reflog(old_branch_info->path); } } remove_branch_state(the_repository); strbuf_release(&msg); if (!opts->quiet && (new_branch_info->path || (!opts->force_detach && !strcmp(new_branch_info->name, "HEAD")))) report_tracking(new_branch_info); }