static int merge_trivial(struct commit *head, struct commit_list *remoteheads) { unsigned char result_tree[20], result_commit[20]; struct commit_list *parents, **pptr = &parents; static struct lock_file lock; hold_locked_index(&lock, 1); refresh_cache(REFRESH_QUIET); if (active_cache_changed && write_locked_index(&the_index, &lock, COMMIT_LOCK)) return error(_("Unable to write index.")); rollback_lock_file(&lock); write_tree_trivial(result_tree); printf(_("Wonderful.\n")); pptr = commit_list_append(head, pptr); pptr = commit_list_append(remoteheads->item, pptr); prepare_to_commit(remoteheads); if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents, result_commit, NULL, sign_commit)) die(_("failed to write commit object")); finish(head, remoteheads, result_commit, "In-index merge"); drop_save(); return 0; }
static int finish_automerge(struct commit_list *common, unsigned char *result_tree, const char *wt_strategy) { struct commit_list *parents = NULL, *j; struct strbuf buf = STRBUF_INIT; unsigned char result_commit[20]; free_commit_list(common); if (allow_fast_forward) { parents = remoteheads; commit_list_insert(lookup_commit(head), &parents); parents = reduce_heads(parents); } else { struct commit_list **pptr = &parents; pptr = &commit_list_insert(lookup_commit(head), pptr)->next; for (j = remoteheads; j; j = j->next) pptr = &commit_list_insert(j->item, pptr)->next; } free_commit_list(remoteheads); strbuf_addch(&merge_msg, '\n'); run_prepare_commit_msg(); commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL); strbuf_addf(&buf, "Merge made by %s.", wt_strategy); finish(result_commit, buf.buf); strbuf_release(&buf); drop_save(); return 0; }
static int finish_automerge(struct commit *head, struct commit_list *common, unsigned char *result_tree, const char *wt_strategy) { struct commit_list *parents = NULL, *j; struct strbuf buf = STRBUF_INIT; unsigned char result_commit[20]; free_commit_list(common); if (allow_fast_forward) { parents = remoteheads; commit_list_insert(head, &parents); parents = reduce_heads(parents); } else { struct commit_list **pptr = &parents; pptr = &commit_list_insert(head, pptr)->next; for (j = remoteheads; j; j = j->next) pptr = &commit_list_insert(j->item, pptr)->next; } strbuf_addch(&merge_msg, '\n'); prepare_to_commit(); free_commit_list(remoteheads); if (commit_tree(&merge_msg, result_tree, parents, result_commit, NULL, sign_commit)) die(_("failed to write commit object")); strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy); finish(head, result_commit, buf.buf); strbuf_release(&buf); drop_save(); return 0; }
gboolean gitg_commit_commit(GitgCommit *commit, gchar const *comment, gboolean signoff, GError **error) { g_return_val_if_fail(GITG_IS_COMMIT(commit), FALSE); gchar *tree; if (!write_tree(commit, &tree, error)) return FALSE; gchar *ref; gboolean ret = commit_tree(commit, tree, comment, signoff, &ref, error); g_free(tree); if (!ret) return FALSE; gchar *subject = comment_parse_subject(comment); ret = update_ref(commit, ref, subject, error); g_free(subject); if (!ret) return FALSE; gitg_repository_reload(commit->priv->repository); return TRUE; }
void create_notes_commit(struct notes_tree *t, struct commit_list *parents, const char *msg, unsigned char *result_sha1) { unsigned char tree_sha1[20]; assert(t->initialized); if (write_notes_tree(t, tree_sha1)) die("Failed to write notes tree to database"); if (!parents) { /* Deduce parent commit from t->ref */ unsigned char parent_sha1[20]; if (!read_ref(t->ref, parent_sha1)) { struct commit *parent = lookup_commit(parent_sha1); if (!parent || parse_commit(parent)) die("Failed to find/parse commit %s", t->ref); commit_list_insert(parent, &parents); } /* else: t->ref points to nothing, assume root/orphan commit */ } if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL)) die("Failed to commit notes tree to database"); }
static int finish_automerge(struct commit *head, int head_subsumed, struct commit_list *common, struct commit_list *remoteheads, unsigned char *result_tree, const char *wt_strategy) { struct commit_list *parents = NULL; struct strbuf buf = STRBUF_INIT; unsigned char result_commit[20]; free_commit_list(common); parents = remoteheads; if (!head_subsumed || !allow_fast_forward) commit_list_insert(head, &parents); strbuf_addch(&merge_msg, '\n'); prepare_to_commit(remoteheads); if (commit_tree(&merge_msg, result_tree, parents, result_commit, NULL, sign_commit)) die(_("failed to write commit object")); strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy); finish(head, remoteheads, result_commit, buf.buf); strbuf_release(&buf); drop_save(); return 0; }
static int merge_trivial(void) { unsigned char result_tree[20], result_commit[20]; struct commit_list parent; write_tree_trivial(result_tree); printf("Wonderful.\n"); parent.item = remoteheads->item; parent.next = NULL; commit_tree(merge_msg.buf, result_tree, &parent, result_commit); finish(result_commit, "In-index merge"); drop_save(); return 0; }
static int merge_trivial(void) { unsigned char result_tree[20], result_commit[20]; struct commit_list *parent = xmalloc(sizeof(*parent)); write_tree_trivial(result_tree); printf("Wonderful.\n"); parent->item = lookup_commit(head); parent->next = xmalloc(sizeof(*parent->next)); parent->next->item = remoteheads->item; parent->next->next = NULL; commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL); finish(result_commit, "In-index merge"); drop_save(); return 0; }
static int merge_trivial(struct commit *head, struct commit_list *remoteheads) { unsigned char result_tree[20], result_commit[20]; struct commit_list *parents, **pptr = &parents; write_tree_trivial(result_tree); printf(_("Wonderful.\n")); pptr = commit_list_append(head, pptr); pptr = commit_list_append(remoteheads->item, pptr); prepare_to_commit(remoteheads); if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents, result_commit, NULL, sign_commit)) die(_("failed to write commit object")); finish(head, remoteheads, result_commit, "In-index merge"); drop_save(); return 0; }
static int merge_trivial(struct commit *head, struct commit_list *remoteheads) { unsigned char result_tree[20], result_commit[20]; struct commit_list *parent = xmalloc(sizeof(*parent)); write_tree_trivial(result_tree); printf(_("Wonderful.\n")); parent->item = head; parent->next = xmalloc(sizeof(*parent->next)); parent->next->item = remoteheads->item; parent->next->next = NULL; prepare_to_commit(remoteheads); if (commit_tree(&merge_msg, result_tree, parent, result_commit, NULL, sign_commit)) die(_("failed to write commit object")); finish(head, remoteheads, result_commit, "In-index merge"); drop_save(); return 0; }
int commit_notes(struct notes_tree *t, const char *msg) { struct commit_list *parent; unsigned char tree_sha1[20], prev_commit[20], new_commit[20]; struct strbuf buf = STRBUF_INIT; if (!t) t = &default_notes_tree; if (!t->initialized || !t->ref || !*t->ref) die("Cannot commit uninitialized/unreferenced notes tree"); if (!t->dirty) return 0; /* don't have to commit an unchanged tree */ /* Prepare commit message and reflog message */ strbuf_addstr(&buf, "notes: "); /* commit message starts at index 7 */ strbuf_addstr(&buf, msg); if (buf.buf[buf.len - 1] != '\n') strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */ /* Convert notes tree to tree object */ if (write_notes_tree(t, tree_sha1)) die("Failed to write current notes tree to database"); /* Create new commit for the tree object */ if (!read_ref(t->ref, prev_commit)) { /* retrieve parent commit */ parent = xmalloc(sizeof(*parent)); parent->item = lookup_commit(prev_commit); parent->next = NULL; } else { hashclr(prev_commit); parent = NULL; } if (commit_tree(buf.buf + 7, tree_sha1, parent, new_commit, NULL)) die("Failed to commit notes tree to database"); /* Update notes ref with new commit */ update_ref(buf.buf, t->ref, new_commit, prev_commit, 0, DIE_ON_ERR); strbuf_release(&buf); return 0; }
int notes_cache_write(struct notes_cache *c) { struct object_id tree_oid, commit_oid; if (!c || !c->tree.initialized || !c->tree.update_ref || !*c->tree.update_ref) return -1; if (!c->tree.dirty) return 0; if (write_notes_tree(&c->tree, &tree_oid)) return -1; if (commit_tree(c->validity, strlen(c->validity), &tree_oid, NULL, &commit_oid, NULL, NULL) < 0) return -1; if (update_ref("update notes cache", c->tree.update_ref, &commit_oid, NULL, 0, UPDATE_REFS_QUIET_ON_ERR) < 0) return -1; return 0; }
int cmd_commit_tree(int argc, const char **argv, const char *prefix) { int i; struct commit_list *parents = NULL; unsigned char tree_sha1[20]; unsigned char commit_sha1[20]; struct strbuf buffer = STRBUF_INIT; git_config(git_default_config, NULL); if (argc < 2 || !strcmp(argv[1], "-h")) usage(commit_tree_usage); if (get_sha1(argv[1], tree_sha1)) die("Not a valid object name %s", argv[1]); for (i = 2; i < argc; i += 2) { unsigned char sha1[20]; const char *a, *b; a = argv[i]; b = argv[i+1]; if (!b || strcmp(a, "-p")) usage(commit_tree_usage); if (get_sha1(b, sha1)) die("Not a valid object name %s", b); assert_sha1_type(sha1, OBJ_COMMIT); new_parent(lookup_commit(sha1), &parents); } if (strbuf_read(&buffer, 0, 0) < 0) die_errno("git commit-tree: failed to read"); if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) { strbuf_release(&buffer); return 1; } printf("%s\n", sha1_to_hex(commit_sha1)); strbuf_release(&buffer); return 0; }
static int save_untracked_files(struct stash_info *info, struct strbuf *msg, struct strbuf files) { int ret = 0; struct strbuf untracked_msg = STRBUF_INIT; struct child_process cp_upd_index = CHILD_PROCESS_INIT; struct index_state istate = { NULL }; cp_upd_index.git_cmd = 1; argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add", "--remove", "--stdin", NULL); argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf); if (pipe_command(&cp_upd_index, files.buf, files.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } if (write_index_as_tree(&info->u_tree, &istate, stash_index_path.buf, 0, NULL)) { ret = -1; goto done; } if (commit_tree(untracked_msg.buf, untracked_msg.len, &info->u_tree, NULL, &info->u_commit, NULL, NULL)) { ret = -1; goto done; } done: discard_index(&istate); strbuf_release(&untracked_msg); remove_path(stash_index_path.buf); return ret; }
int notes_cache_write(struct notes_cache *c) { unsigned char tree_sha1[20]; unsigned char commit_sha1[20]; struct strbuf msg = STRBUF_INIT; if (!c || !c->tree.initialized || !c->tree.ref || !*c->tree.ref) return -1; if (!c->tree.dirty) return 0; if (write_notes_tree(&c->tree, tree_sha1)) return -1; strbuf_attach(&msg, c->validity, strlen(c->validity), strlen(c->validity) + 1); if (commit_tree(&msg, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0) return -1; if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL, 0, QUIET_ON_ERR) < 0) return -1; return 0; }
int cmd_commit(int argc, const char **argv, const char *prefix) { struct strbuf sb = STRBUF_INIT; const char *index_file, *reflog_msg; char *nl, *p; unsigned char commit_sha1[20]; struct ref_lock *ref_lock; struct commit_list *parents = NULL, **pptr = &parents; struct stat statbuf; int allow_fast_forward = 1; struct wt_status s; wt_status_prepare(&s); git_config(git_commit_config, &s); in_merge = file_exists(git_path("MERGE_HEAD")); s.in_merge = in_merge; if (s.use_color == -1) s.use_color = git_use_color_default; argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix, &s); if (dry_run) { if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; return dry_run_commit(argc, argv, prefix, &s); } index_file = prepare_index(argc, argv, prefix, 0); /* Set up everything for writing the commit object. This includes running hooks, writing the trees, and interacting with the user. */ if (!prepare_to_commit(index_file, prefix, &s)) { rollback_index_files(); return 1; } /* Determine parents */ reflog_msg = getenv("GIT_REFLOG_ACTION"); if (initial_commit) { if (!reflog_msg) reflog_msg = "commit (initial)"; } else if (amend) { struct commit_list *c; struct commit *commit; if (!reflog_msg) reflog_msg = "commit (amend)"; commit = lookup_commit(head_sha1); if (!commit || parse_commit(commit)) die("could not parse HEAD commit"); for (c = commit->parents; c; c = c->next) pptr = &commit_list_insert(c->item, pptr)->next; } else if (in_merge) { struct strbuf m = STRBUF_INIT; FILE *fp; if (!reflog_msg) reflog_msg = "commit (merge)"; pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next; fp = fopen(git_path("MERGE_HEAD"), "r"); if (fp == NULL) die_errno("could not open '%s' for reading", git_path("MERGE_HEAD")); while (strbuf_getline(&m, fp, '\n') != EOF) { unsigned char sha1[20]; if (get_sha1_hex(m.buf, sha1) < 0) die("Corrupt MERGE_HEAD file (%s)", m.buf); pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next; } fclose(fp); strbuf_release(&m); if (!stat(git_path("MERGE_MODE"), &statbuf)) { if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0) die_errno("could not read MERGE_MODE"); if (!strcmp(sb.buf, "no-ff")) allow_fast_forward = 0; } if (allow_fast_forward) parents = reduce_heads(parents); } else { if (!reflog_msg) reflog_msg = "commit"; pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next; } /* Finally, get the commit message */ strbuf_reset(&sb); if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) { int saved_errno = errno; rollback_index_files(); die("could not read commit message: %s", strerror(saved_errno)); } /* Truncate the message just before the diff, if any. */ if (verbose) { p = strstr(sb.buf, "\ndiff --git "); if (p != NULL) strbuf_setlen(&sb, p - sb.buf + 1); } if (cleanup_mode != CLEANUP_NONE) stripspace(&sb, cleanup_mode == CLEANUP_ALL); if (message_is_empty(&sb) && !allow_empty_message) { rollback_index_files(); fprintf(stderr, "Aborting commit due to empty commit message.\n"); exit(1); } if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1, fmt_ident(author_name, author_email, author_date, IDENT_ERROR_ON_NO_NAME))) { rollback_index_files(); die("failed to write commit object"); } ref_lock = lock_any_ref_for_update("HEAD", initial_commit ? NULL : head_sha1, 0); nl = strchr(sb.buf, '\n'); if (nl) strbuf_setlen(&sb, nl + 1 - sb.buf); else strbuf_addch(&sb, '\n'); strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg)); strbuf_insert(&sb, strlen(reflog_msg), ": ", 2); if (!ref_lock) { rollback_index_files(); die("cannot lock HEAD ref"); } if (write_ref_sha1(ref_lock, commit_sha1, sb.buf) < 0) { rollback_index_files(); die("cannot update HEAD ref"); } unlink(git_path("MERGE_HEAD")); unlink(git_path("MERGE_MSG")); unlink(git_path("MERGE_MODE")); unlink(git_path("SQUASH_MSG")); if (commit_index_files()) die ("Repository has been updated, but unable to write\n" "new_index file. Check that disk is not full or quota is\n" "not exceeded, and then \"git reset HEAD\" to recover."); rerere(0); run_hook(get_index_file(), "post-commit", NULL); if (amend && !no_post_rewrite) { struct notes_rewrite_cfg *cfg; cfg = init_copy_notes_for_rewrite("amend"); if (cfg) { copy_note_for_rewrite(cfg, head_sha1, commit_sha1); finish_copy_notes_for_rewrite(cfg); } run_rewrite_hook(head_sha1, commit_sha1); } if (!quiet) print_summary(prefix, commit_sha1); return 0; }
static int do_create_stash(struct pathspec ps, struct strbuf *stash_msg_buf, int include_untracked, int patch_mode, struct stash_info *info, struct strbuf *patch, int quiet) { int ret = 0; int flags = 0; int untracked_commit_option = 0; const char *head_short_sha1 = NULL; const char *branch_ref = NULL; const char *branch_name = "(no branch)"; struct commit *head_commit = NULL; struct commit_list *parents = NULL; struct strbuf msg = STRBUF_INIT; struct strbuf commit_tree_label = STRBUF_INIT; struct strbuf untracked_files = STRBUF_INIT; prepare_fallback_ident("git stash", "git@stash"); read_cache_preload(NULL); refresh_cache(REFRESH_QUIET); if (get_oid("HEAD", &info->b_commit)) { if (!quiet) fprintf_ln(stderr, _("You do not have " "the initial commit yet")); ret = -1; goto done; } else { head_commit = lookup_commit(the_repository, &info->b_commit); } if (!check_changes(ps, include_untracked, &untracked_files)) { ret = 1; goto done; } branch_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flags); if (flags & REF_ISSYMREF) branch_name = strrchr(branch_ref, '/') + 1; head_short_sha1 = find_unique_abbrev(&head_commit->object.oid, DEFAULT_ABBREV); strbuf_addf(&msg, "%s: %s ", branch_name, head_short_sha1); pp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg); strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf); commit_list_insert(head_commit, &parents); if (write_cache_as_tree(&info->i_tree, 0, NULL) || commit_tree(commit_tree_label.buf, commit_tree_label.len, &info->i_tree, parents, &info->i_commit, NULL, NULL)) { if (!quiet) fprintf_ln(stderr, _("Cannot save the current " "index state")); ret = -1; goto done; } if (include_untracked) { if (save_untracked_files(info, &msg, untracked_files)) { if (!quiet) fprintf_ln(stderr, _("Cannot save " "the untracked files")); ret = -1; goto done; } untracked_commit_option = 1; } if (patch_mode) { ret = stash_patch(info, ps, patch, quiet); if (ret < 0) { if (!quiet) fprintf_ln(stderr, _("Cannot save the current " "worktree state")); goto done; } else if (ret > 0) { goto done; } } else { if (stash_working_tree(info, ps)) { if (!quiet) fprintf_ln(stderr, _("Cannot save the current " "worktree state")); ret = -1; goto done; } } if (!stash_msg_buf->len) strbuf_addf(stash_msg_buf, "WIP on %s", msg.buf); else strbuf_insertf(stash_msg_buf, 0, "On %s: ", branch_name); /* * `parents` will be empty after calling `commit_tree()`, so there is * no need to call `free_commit_list()` */ parents = NULL; if (untracked_commit_option) commit_list_insert(lookup_commit(the_repository, &info->u_commit), &parents); commit_list_insert(lookup_commit(the_repository, &info->i_commit), &parents); commit_list_insert(head_commit, &parents); if (commit_tree(stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree, parents, &info->w_commit, NULL, NULL)) { if (!quiet) fprintf_ln(stderr, _("Cannot record " "working tree state")); ret = -1; goto done; } done: strbuf_release(&commit_tree_label); strbuf_release(&msg); strbuf_release(&untracked_files); return ret; }
int cmd_commit_tree(int argc, const char **argv, const char *prefix) { int i, got_tree = 0; struct commit_list *parents = NULL; unsigned char tree_sha1[20]; unsigned char commit_sha1[20]; struct strbuf buffer = STRBUF_INIT; git_config(commit_tree_config, NULL); if (argc < 2 || !strcmp(argv[1], "-h")) usage(commit_tree_usage); for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "-p")) { unsigned char sha1[20]; if (argc <= ++i) usage(commit_tree_usage); if (get_sha1_commit(argv[i], sha1)) die("Not a valid object name %s", argv[i]); assert_sha1_type(sha1, OBJ_COMMIT); new_parent(lookup_commit(sha1), &parents); continue; } if (skip_prefix(arg, "-S", &sign_commit)) continue; if (!strcmp(arg, "--no-gpg-sign")) { sign_commit = NULL; continue; } if (!strcmp(arg, "-m")) { if (argc <= ++i) usage(commit_tree_usage); if (buffer.len) strbuf_addch(&buffer, '\n'); strbuf_addstr(&buffer, argv[i]); strbuf_complete_line(&buffer); continue; } if (!strcmp(arg, "-F")) { int fd; if (argc <= ++i) usage(commit_tree_usage); if (buffer.len) strbuf_addch(&buffer, '\n'); if (!strcmp(argv[i], "-")) fd = 0; else { fd = open(argv[i], O_RDONLY); if (fd < 0) die_errno("git commit-tree: failed to open '%s'", argv[i]); } if (strbuf_read(&buffer, fd, 0) < 0) die_errno("git commit-tree: failed to read '%s'", argv[i]); if (fd && close(fd)) die_errno("git commit-tree: failed to close '%s'", argv[i]); strbuf_complete_line(&buffer); continue; } if (get_sha1_tree(arg, tree_sha1)) die("Not a valid object name %s", arg); if (got_tree) die("Cannot give more than one trees"); got_tree = 1; } if (!buffer.len) { if (strbuf_read(&buffer, 0, 0) < 0) die_errno("git commit-tree: failed to read"); } if (commit_tree(buffer.buf, buffer.len, tree_sha1, parents, commit_sha1, NULL, sign_commit)) { strbuf_release(&buffer); return 1; } printf("%s\n", sha1_to_hex(commit_sha1)); strbuf_release(&buffer); return 0; }