* Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano
*/
#include "builtin.h"
+#include "lockfile.h"
#include "tag.h"
#include "object.h"
#include "commit.h"
static inline int is_merge(void)
{
- return !access(git_path("MERGE_HEAD"), F_OK);
+ return !access(git_path_merge_head(), F_OK);
}
static int reset_index(const unsigned char *sha1, int reset_type, int quiet)
if (reset_type == MIXED || reset_type == HARD) {
tree = parse_tree_indirect(sha1);
- prime_cache_tree(&active_cache_tree, tree);
+ prime_cache_tree(&the_index, tree);
}
return 0;
static void print_new_head_line(struct commit *commit)
{
const char *hex, *body;
- char *msg;
+ const char *msg;
- hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
+ hex = find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV);
printf(_("HEAD is now at %s"), hex);
msg = logmsg_reencode(commit, NULL, get_log_output_encoding());
body = strstr(msg, "\n\n");
}
else
printf("\n");
- logmsg_free(msg, commit);
+ unuse_commit_buffer(commit, msg);
}
static void update_index_from_diff(struct diff_queue_struct *q,
struct diff_options *opt, void *data)
{
int i;
+ int intent_to_add = *(int *)data;
for (i = 0; i < q->nr; i++) {
struct diff_filespec *one = q->queue[i]->one;
- if (one->mode && !is_null_sha1(one->sha1)) {
- struct cache_entry *ce;
- ce = make_cache_entry(one->mode, one->sha1, one->path,
- 0, 0);
- if (!ce)
- die(_("make_cache_entry failed for path '%s'"),
- one->path);
- add_cache_entry(ce, ADD_CACHE_OK_TO_ADD |
- ADD_CACHE_OK_TO_REPLACE);
- } else
+ int is_missing = !(one->mode && !is_null_sha1(one->sha1));
+ struct cache_entry *ce;
+
+ if (is_missing && !intent_to_add) {
remove_file_from_cache(one->path);
+ continue;
+ }
+
+ ce = make_cache_entry(one->mode, one->sha1, one->path,
+ 0, 0);
+ if (!ce)
+ die(_("make_cache_entry failed for path '%s'"),
+ one->path);
+ if (is_missing) {
+ ce->ce_flags |= CE_INTENT_TO_ADD;
+ set_object_name_for_intent_to_add_entry(ce);
+ }
+ add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
}
}
static int read_from_tree(const struct pathspec *pathspec,
- unsigned char *tree_sha1)
+ unsigned char *tree_sha1,
+ int intent_to_add)
{
struct diff_options opt;
copy_pathspec(&opt.pathspec, pathspec);
opt.output_format = DIFF_FORMAT_CALLBACK;
opt.format_callback = update_index_from_diff;
+ opt.format_callback_data = &intent_to_add;
if (do_diff_cache(tree_sha1, &opt))
return 1;
if (!get_sha1("HEAD", sha1_orig)) {
orig = sha1_orig;
set_reflog_message(&msg, "updating ORIG_HEAD", NULL);
- update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
+ update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
+ UPDATE_REFS_MSG_ON_ERR);
} else if (old_orig)
delete_ref("ORIG_HEAD", old_orig, 0);
set_reflog_message(&msg, "updating HEAD", rev);
- update_ref_status = update_ref(msg.buf, "HEAD", sha1, orig, 0, MSG_ON_ERR);
+ update_ref_status = update_ref(msg.buf, "HEAD", sha1, orig, 0,
+ UPDATE_REFS_MSG_ON_ERR);
strbuf_release(&msg);
return update_ref_status;
}
int reset_type = NONE, update_ref_status = 0, quiet = 0;
int patch_mode = 0, unborn;
const char *rev;
- unsigned char sha1[20];
+ struct object_id oid;
struct pathspec pathspec;
+ int intent_to_add = 0;
const struct option options[] = {
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
OPT_SET_INT(0, "mixed", &reset_type,
OPT_SET_INT(0, "keep", &reset_type,
N_("reset HEAD but keep local changes"), KEEP),
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
+ OPT_BOOL('N', "intent-to-add", &intent_to_add,
+ N_("record only the fact that removed paths will be added later")),
OPT_END()
};
PARSE_OPT_KEEP_DASHDASH);
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
- unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", sha1);
+ unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", oid.hash);
if (unborn) {
/* reset on unborn branch: treat as reset to empty tree */
- hashcpy(sha1, EMPTY_TREE_SHA1_BIN);
+ hashcpy(oid.hash, EMPTY_TREE_SHA1_BIN);
} else if (!pathspec.nr) {
struct commit *commit;
- if (get_sha1_committish(rev, sha1))
+ if (get_sha1_committish(rev, oid.hash))
die(_("Failed to resolve '%s' as a valid revision."), rev);
- commit = lookup_commit_reference(sha1);
+ commit = lookup_commit_reference(oid.hash);
if (!commit)
die(_("Could not parse object '%s'."), rev);
- hashcpy(sha1, commit->object.sha1);
+ oidcpy(&oid, &commit->object.oid);
} else {
struct tree *tree;
- if (get_sha1_treeish(rev, sha1))
+ if (get_sha1_treeish(rev, oid.hash))
die(_("Failed to resolve '%s' as a valid tree."), rev);
- tree = parse_tree_indirect(sha1);
+ tree = parse_tree_indirect(oid.hash);
if (!tree)
die(_("Could not parse object '%s'."), rev);
- hashcpy(sha1, tree->object.sha1);
+ oidcpy(&oid, &tree->object.oid);
}
if (patch_mode) {
die(_("%s reset is not allowed in a bare repository"),
_(reset_type_names[reset_type]));
+ if (intent_to_add && reset_type != MIXED)
+ die(_("-N can only be used with --mixed"));
+
/* Soft reset does not touch the index file nor the working tree
* at all, but requires them in a good order. Other resets reset
* the index file to the tree object we are switching to. */
if (reset_type != SOFT) {
struct lock_file *lock = xcalloc(1, sizeof(*lock));
- int newfd = hold_locked_index(lock, 1);
+ hold_locked_index(lock, 1);
if (reset_type == MIXED) {
int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
- if (read_from_tree(&pathspec, sha1))
+ if (read_from_tree(&pathspec, oid.hash, intent_to_add))
return 1;
if (get_git_work_tree())
refresh_index(&the_index, flags, NULL, NULL,
_("Unstaged changes after reset:"));
} else {
- int err = reset_index(sha1, reset_type, quiet);
+ int err = reset_index(oid.hash, reset_type, quiet);
if (reset_type == KEEP && !err)
- err = reset_index(sha1, MIXED, quiet);
+ err = reset_index(oid.hash, MIXED, quiet);
if (err)
die(_("Could not reset index file to revision '%s'."), rev);
}
- if (write_cache(newfd, active_cache, active_nr) ||
- commit_locked_index(lock))
+ if (write_locked_index(&the_index, lock, COMMIT_LOCK))
die(_("Could not write new index file."));
}
if (!pathspec.nr && !unborn) {
/* Any resets without paths update HEAD to the head being
* switched to, saving the previous head in ORIG_HEAD before. */
- update_ref_status = reset_refs(rev, sha1);
+ update_ref_status = reset_refs(rev, oid.hash);
if (reset_type == HARD && !update_ref_status && !quiet)
- print_new_head_line(lookup_commit_reference(sha1));
+ print_new_head_line(lookup_commit_reference(oid.hash));
}
if (!pathspec.nr)
remove_branch_state();