* [PATCH v2 1/6] refs.c: add err arguments to reflog functions
@ 2015-06-25 20:45 David Turner
2015-06-25 20:45 ` [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs David Turner
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: David Turner @ 2015-06-25 20:45 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner, Ronnie Sahlberg, David Turner
Add an err argument to log_ref_setup that can explain the reason
for a failure. This then eliminates the need to manage errno through
this function since we can just add strerror(errno) to the err string
when meaningful. No callers relied on errno from this function for
anything else than the error message.
Also add err arguments to private functions write_ref_to_lockfile,
log_ref_write_1, commit_ref_update. This again eliminates the need to
manage errno in these functions.
Update of a patch by Ronnie Sahlberg.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: David Turner <dturner@twitter.com>
---
builtin/checkout.c | 8 ++--
refs.c | 111 ++++++++++++++++++++++++++++-------------------------
refs.h | 4 +-
3 files changed, 66 insertions(+), 57 deletions(-)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index c018ab3..93f63d3 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -624,16 +624,18 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
struct strbuf log_file = STRBUF_INIT;
int ret;
const char *ref_name;
+ struct strbuf err = STRBUF_INIT;
ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch);
temp = log_all_ref_updates;
log_all_ref_updates = 1;
- ret = log_ref_setup(ref_name, &log_file);
+ ret = log_ref_setup(ref_name, &log_file, &err);
log_all_ref_updates = temp;
strbuf_release(&log_file);
if (ret) {
- fprintf(stderr, _("Can not do reflog for '%s'\n"),
- opts->new_orphan_branch);
+ fprintf(stderr, _("Can not do reflog for '%s'. %s\n"),
+ opts->new_orphan_branch, err.buf);
+ strbuf_release(&err);
return;
}
}
diff --git a/refs.c b/refs.c
index fb568d7..b34a54a 100644
--- a/refs.c
+++ b/refs.c
@@ -2975,9 +2975,11 @@ static int rename_ref_available(const char *oldname, const char *newname)
return ret;
}
-static int write_ref_to_lockfile(struct ref_lock *lock, const unsigned char *sha1);
+static int write_ref_to_lockfile(struct ref_lock *lock,
+ const unsigned char *sha1, struct strbuf* err);
static int commit_ref_update(struct ref_lock *lock,
- const unsigned char *sha1, const char *logmsg);
+ const unsigned char *sha1, const char *logmsg,
+ struct strbuf *err);
int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)
{
@@ -3038,9 +3040,10 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
}
hashcpy(lock->old_oid.hash, orig_sha1);
- if (write_ref_to_lockfile(lock, orig_sha1) ||
- commit_ref_update(lock, orig_sha1, logmsg)) {
- error("unable to write current sha1 into %s", newrefname);
+ if (write_ref_to_lockfile(lock, orig_sha1, &err) ||
+ commit_ref_update(lock, orig_sha1, logmsg, &err)) {
+ error("unable to write current sha1 into %s: %s", newrefname, err.buf);
+ strbuf_release(&err);
goto rollback;
}
@@ -3056,9 +3059,11 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
flag = log_all_ref_updates;
log_all_ref_updates = 0;
- if (write_ref_to_lockfile(lock, orig_sha1) ||
- commit_ref_update(lock, orig_sha1, NULL))
- error("unable to write current sha1 into %s", oldrefname);
+ if (write_ref_to_lockfile(lock, orig_sha1, &err) ||
+ commit_ref_update(lock, orig_sha1, NULL, &err)) {
+ error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
+ strbuf_release(&err);
+ }
log_all_ref_updates = flag;
rollbacklog:
@@ -3113,8 +3118,8 @@ static int copy_msg(char *buf, const char *msg)
return cp - buf;
}
-/* This function must set a meaningful errno on failure */
-int log_ref_setup(const char *refname, struct strbuf *sb_logfile)
+/* This function will fill in *err and return -1 on failure */
+int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf *err)
{
int logfd, oflags = O_APPEND | O_WRONLY;
char *logfile;
@@ -3129,9 +3134,8 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile)
starts_with(refname, "refs/notes/") ||
!strcmp(refname, "HEAD"))) {
if (safe_create_leading_directories(logfile) < 0) {
- int save_errno = errno;
- error("unable to create directory for %s", logfile);
- errno = save_errno;
+ strbuf_addf(err, "unable to create directory for %s. "
+ "%s", logfile, strerror(errno));
return -1;
}
oflags |= O_CREAT;
@@ -3144,20 +3148,16 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile)
if (errno == EISDIR) {
if (remove_empty_directories(logfile)) {
- int save_errno = errno;
- error("There are still logs under '%s'",
- logfile);
- errno = save_errno;
+ strbuf_addf(err, "There are still logs under "
+ "'%s'", logfile);
return -1;
}
logfd = open(logfile, oflags, 0666);
}
if (logfd < 0) {
- int save_errno = errno;
- error("Unable to append to %s: %s", logfile,
- strerror(errno));
- errno = save_errno;
+ strbuf_addf(err, "Unable to append to %s: %s",
+ logfile, strerror(errno));
return -1;
}
}
@@ -3195,7 +3195,7 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,
const unsigned char *new_sha1, const char *msg,
- struct strbuf *sb_log_file)
+ struct strbuf *sb_log_file, struct strbuf *err)
{
int logfd, result, oflags = O_APPEND | O_WRONLY;
char *log_file;
@@ -3203,7 +3203,8 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,
if (log_all_ref_updates < 0)
log_all_ref_updates = !is_bare_repository();
- result = log_ref_setup(refname, sb_log_file);
+ result = log_ref_setup(refname, sb_log_file, err);
+
if (result)
return result;
log_file = sb_log_file->buf;
@@ -3216,26 +3217,25 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,
result = log_ref_write_fd(logfd, old_sha1, new_sha1,
git_committer_info(0), msg);
if (result) {
- int save_errno = errno;
close(logfd);
- error("Unable to append to %s", log_file);
- errno = save_errno;
+ strbuf_addf(err, "Unable to append to %s. %s", log_file,
+ strerror(errno));
return -1;
}
if (close(logfd)) {
- int save_errno = errno;
- error("Unable to append to %s", log_file);
- errno = save_errno;
+ strbuf_addf(err, "Unable to append to %s. %s", log_file,
+ strerror(errno));
return -1;
}
return 0;
}
static int log_ref_write(const char *refname, const unsigned char *old_sha1,
- const unsigned char *new_sha1, const char *msg)
+ const unsigned char *new_sha1, const char *msg,
+ struct strbuf *err)
{
struct strbuf sb = STRBUF_INIT;
- int ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb);
+ int ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb, err);
strbuf_release(&sb);
return ret;
}
@@ -3247,25 +3247,28 @@ int is_branch(const char *refname)
/*
* Write sha1 into the open lockfile, then close the lockfile. On
- * errors, rollback the lockfile and set errno to reflect the problem.
+ * errors, rollback the lockfile, fill in *err and
+ * return -1.
*/
static int write_ref_to_lockfile(struct ref_lock *lock,
- const unsigned char *sha1)
+ const unsigned char *sha1, struct strbuf *err)
{
static char term = '\n';
struct object *o;
o = parse_object(sha1);
if (!o) {
- error("Trying to write ref %s with nonexistent object %s",
- lock->ref_name, sha1_to_hex(sha1));
+ strbuf_addf(err,
+ "Trying to write ref %s with nonexistent object %s",
+ lock->ref_name, sha1_to_hex(sha1));
unlock_ref(lock);
errno = EINVAL;
return -1;
}
if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
- error("Trying to write non-commit object %s to branch %s",
- sha1_to_hex(sha1), lock->ref_name);
+ strbuf_addf(err,
+ "Trying to write non-commit object %s to branch %s",
+ sha1_to_hex(sha1), lock->ref_name);
unlock_ref(lock);
errno = EINVAL;
return -1;
@@ -3273,10 +3276,9 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
if (write_in_full(lock->lk->fd, sha1_to_hex(sha1), 40) != 40 ||
write_in_full(lock->lk->fd, &term, 1) != 1 ||
close_ref(lock) < 0) {
- int save_errno = errno;
- error("Couldn't write %s", lock->lk->filename.buf);
+ strbuf_addf(err,
+ "Couldn't write %s", lock->lk->filename.buf);
unlock_ref(lock);
- errno = save_errno;
return -1;
}
return 0;
@@ -3288,12 +3290,15 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
* necessary, using the specified lockmsg (which can be NULL).
*/
static int commit_ref_update(struct ref_lock *lock,
- const unsigned char *sha1, const char *logmsg)
+ const unsigned char *sha1, const char *logmsg,
+ struct strbuf *err)
{
clear_loose_ref_cache(&ref_cache);
- if (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg) < 0 ||
+ if (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0 ||
(strcmp(lock->ref_name, lock->orig_ref_name) &&
- log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg) < 0)) {
+ log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0)) {
+ strbuf_addf(err, "Cannot update the ref '%s'.",
+ lock->ref_name);
unlock_ref(lock);
return -1;
}
@@ -3317,7 +3322,8 @@ static int commit_ref_update(struct ref_lock *lock,
head_sha1, &head_flag);
if (head_ref && (head_flag & REF_ISSYMREF) &&
!strcmp(head_ref, lock->ref_name))
- log_ref_write("HEAD", lock->old_oid.hash, sha1, logmsg);
+ log_ref_write("HEAD", lock->old_oid.hash, sha1, logmsg,
+ err);
}
if (commit_ref(lock)) {
error("Couldn't set %s", lock->ref_name);
@@ -3336,6 +3342,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
int fd, len, written;
char *git_HEAD = git_pathdup("%s", ref_target);
unsigned char old_sha1[20], new_sha1[20];
+ struct strbuf err = STRBUF_INIT;
if (logmsg && read_ref(ref_target, old_sha1))
hashclr(old_sha1);
@@ -3384,8 +3391,11 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
#ifndef NO_SYMLINK_HEAD
done:
#endif
- if (logmsg && !read_ref(refs_heads_master, new_sha1))
- log_ref_write(ref_target, old_sha1, new_sha1, logmsg);
+ if (logmsg && !read_ref(refs_heads_master, new_sha1) &&
+ log_ref_write(ref_target, old_sha1, new_sha1, logmsg, &err)) {
+ error("%s", err.buf);
+ strbuf_release(&err);
+ }
free(git_HEAD);
return 0;
@@ -4021,14 +4031,13 @@ int ref_transaction_commit(struct ref_transaction *transaction,
* value, so we don't need to write it.
*/
} else if (write_ref_to_lockfile(update->lock,
- update->new_sha1)) {
+ update->new_sha1,
+ err)) {
/*
* The lock was freed upon failure of
* write_ref_to_lockfile():
*/
update->lock = NULL;
- strbuf_addf(err, "cannot update the ref '%s'.",
- update->refname);
ret = TRANSACTION_GENERIC_ERROR;
goto cleanup;
} else {
@@ -4054,11 +4063,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
if (update->flags & REF_NEEDS_COMMIT) {
if (commit_ref_update(update->lock,
- update->new_sha1, update->msg)) {
+ update->new_sha1, update->msg, err)) {
/* freed by commit_ref_update(): */
update->lock = NULL;
- strbuf_addf(err, "Cannot update the ref '%s'.",
- update->refname);
ret = TRANSACTION_GENERIC_ERROR;
goto cleanup;
} else {
diff --git a/refs.h b/refs.h
index e82fca5..debdefc 100644
--- a/refs.h
+++ b/refs.h
@@ -226,9 +226,9 @@ int pack_refs(unsigned int flags);
#define REF_NODEREF 0x01
/*
- * Setup reflog before using. Set errno to something meaningful on failure.
+ * Setup reflog before using. Fill in err and return -1 on failure.
*/
-int log_ref_setup(const char *refname, struct strbuf *logfile);
+int log_ref_setup(const char *refname, struct strbuf *logfile, struct strbuf *err);
/** Reads log for the value of ref during at_time. **/
extern int read_ref_at(const char *refname, unsigned int flags,
--
2.0.4.314.gdbf7a51-twtrsrc
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs
2015-06-25 20:45 [PATCH v2 1/6] refs.c: add err arguments to reflog functions David Turner
@ 2015-06-25 20:45 ` David Turner
2015-06-25 21:11 ` Junio C Hamano
2015-06-25 20:45 ` [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START David Turner
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: David Turner @ 2015-06-25 20:45 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner
Instead of directly writing to and reading from files in
$GIT_DIR, use ref API to interact with CHERRY_PICK_HEAD
and REVERT_HEAD.
Signed-off-by: David Turner <dturner@twopensource.com>
---
branch.c | 4 ++--
builtin/commit.c | 6 +++---
builtin/merge.c | 2 +-
contrib/completion/git-prompt.sh | 4 ++--
git-gui/lib/commit.tcl | 2 +-
refs.c | 32 +++++++++++++++++++-------------
sequencer.c | 37 +++++++++++++++++++------------------
t/t7509-commit.sh | 4 ++--
wt-status.c | 6 ++----
9 files changed, 51 insertions(+), 46 deletions(-)
diff --git a/branch.c b/branch.c
index b002435..ec598aa 100644
--- a/branch.c
+++ b/branch.c
@@ -302,8 +302,8 @@ void create_branch(const char *head,
void remove_branch_state(void)
{
- unlink(git_path("CHERRY_PICK_HEAD"));
- unlink(git_path("REVERT_HEAD"));
+ delete_ref("CHERRY_PICK_HEAD", NULL, REF_NODEREF);
+ delete_ref("REVERT_HEAD", NULL, REF_NODEREF);
unlink(git_path("MERGE_HEAD"));
unlink(git_path("MERGE_RR"));
unlink(git_path("MERGE_MSG"));
diff --git a/builtin/commit.c b/builtin/commit.c
index b5b1158..53c7e90 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -168,7 +168,7 @@ static void determine_whence(struct wt_status *s)
{
if (file_exists(git_path("MERGE_HEAD")))
whence = FROM_MERGE;
- else if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
+ else if (ref_exists("CHERRY_PICK_HEAD")) {
whence = FROM_CHERRY_PICK;
if (file_exists(git_path(SEQ_DIR)))
sequencer_in_use = 1;
@@ -1777,8 +1777,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
}
ref_transaction_free(transaction);
- unlink(git_path("CHERRY_PICK_HEAD"));
- unlink(git_path("REVERT_HEAD"));
+ delete_ref("CHERRY_PICK_HEAD", NULL, REF_NODEREF);
+ delete_ref("REVERT_HEAD", NULL, REF_NODEREF);
unlink(git_path("MERGE_HEAD"));
unlink(git_path("MERGE_MSG"));
unlink(git_path("MERGE_MODE"));
diff --git a/builtin/merge.c b/builtin/merge.c
index 46aacd6..3e2ae2f 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1206,7 +1206,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
else
die(_("You have not concluded your merge (MERGE_HEAD exists)."));
}
- if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
+ if (ref_exists("CHERRY_PICK_HEAD")) {
if (advice_resolve_conflict)
die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
"Please, commit your changes before you merge."));
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 366f0bc..e2c5583 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -415,9 +415,9 @@ __git_ps1 ()
fi
elif [ -f "$g/MERGE_HEAD" ]; then
r="|MERGING"
- elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+ elif git rev-parse --quiet --verify "CHERRY_PICK_HEAD" >/dev/null; then
r="|CHERRY-PICKING"
- elif [ -f "$g/REVERT_HEAD" ]; then
+ elif git rev-parse --quiet --verify "REVERT_HEAD" >/dev/null; then
r="|REVERTING"
elif [ -f "$g/BISECT_LOG" ]; then
r="|BISECTING"
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index 864b687..2b08b13 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -409,7 +409,7 @@ A rescan will be automatically started now.
catch {file delete [gitdir MERGE_MSG]}
catch {file delete [gitdir SQUASH_MSG]}
catch {file delete [gitdir GITGUI_MSG]}
- catch {file delete [gitdir CHERRY_PICK_HEAD]}
+ catch {git update-ref -d --no-deref CHERRY_PICK_HEAD}
# -- Let rerere do its thing.
#
diff --git a/refs.c b/refs.c
index b34a54a..de7b5ef 100644
--- a/refs.c
+++ b/refs.c
@@ -2979,7 +2979,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
const unsigned char *sha1, struct strbuf* err);
static int commit_ref_update(struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg,
- struct strbuf *err);
+ struct strbuf *err, int flags);
int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)
{
@@ -3041,7 +3041,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
hashcpy(lock->old_oid.hash, orig_sha1);
if (write_ref_to_lockfile(lock, orig_sha1, &err) ||
- commit_ref_update(lock, orig_sha1, logmsg, &err)) {
+ commit_ref_update(lock, orig_sha1, logmsg, &err, 0)) {
error("unable to write current sha1 into %s: %s", newrefname, err.buf);
strbuf_release(&err);
goto rollback;
@@ -3060,7 +3060,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
flag = log_all_ref_updates;
log_all_ref_updates = 0;
if (write_ref_to_lockfile(lock, orig_sha1, &err) ||
- commit_ref_update(lock, orig_sha1, NULL, &err)) {
+ commit_ref_update(lock, orig_sha1, NULL, &err, 0)) {
error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
strbuf_release(&err);
}
@@ -3118,6 +3118,14 @@ static int copy_msg(char *buf, const char *msg)
return cp - buf;
}
+static int should_autocreate_reflog(const char *refname)
+{
+ return starts_with(refname, "refs/heads/") ||
+ starts_with(refname, "refs/remotes/") ||
+ starts_with(refname, "refs/notes/") ||
+ !strcmp(refname, "HEAD");
+}
+
/* This function will fill in *err and return -1 on failure */
int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf *err)
{
@@ -3128,11 +3136,7 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf
logfile = sb_logfile->buf;
/* make sure the rest of the function can't change "logfile" */
sb_logfile = NULL;
- if (log_all_ref_updates &&
- (starts_with(refname, "refs/heads/") ||
- starts_with(refname, "refs/remotes/") ||
- starts_with(refname, "refs/notes/") ||
- !strcmp(refname, "HEAD"))) {
+ if (log_all_ref_updates && should_autocreate_reflog(refname)) {
if (safe_create_leading_directories(logfile) < 0) {
strbuf_addf(err, "unable to create directory for %s. "
"%s", logfile, strerror(errno));
@@ -3291,12 +3295,14 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
*/
static int commit_ref_update(struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg,
- struct strbuf *err)
+ struct strbuf *err, int flags)
{
clear_loose_ref_cache(&ref_cache);
- if (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0 ||
- (strcmp(lock->ref_name, lock->orig_ref_name) &&
- log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0)) {
+ if ((should_autocreate_reflog(lock->ref_name) ||
+ reflog_exists(lock->ref_name)) &&
+ (log_ref_write(lock->ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0 ||
+ (strcmp(lock->ref_name, lock->orig_ref_name) &&
+ log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg, err) < 0))) {
strbuf_addf(err, "Cannot update the ref '%s'.",
lock->ref_name);
unlock_ref(lock);
@@ -4063,7 +4069,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
if (update->flags & REF_NEEDS_COMMIT) {
if (commit_ref_update(update->lock,
- update->new_sha1, update->msg, err)) {
+ update->new_sha1, update->msg, err, 0)) {
/* freed by commit_ref_update(): */
update->lock = NULL;
ret = TRANSACTION_GENERIC_ERROR;
diff --git a/sequencer.c b/sequencer.c
index f8421a8..de904aa 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -160,19 +160,20 @@ static void free_message(struct commit *commit, struct commit_message *msg)
static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
{
- const char *filename;
- int fd;
- struct strbuf buf = STRBUF_INIT;
+ struct strbuf err = STRBUF_INIT;
+ void *transaction;
- strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
+ transaction = ref_transaction_begin(&err);
+ if (!transaction)
+ die(_("Could not create transaction: %s"), err.buf);
- filename = git_path("%s", pseudoref);
- fd = open(filename, O_WRONLY | O_CREAT, 0666);
- if (fd < 0)
- die_errno(_("Could not open '%s' for writing"), filename);
- if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))
- die_errno(_("Could not write to '%s'"), filename);
- strbuf_release(&buf);
+ if (ref_transaction_update(transaction, pseudoref, commit->object.sha1,
+ NULL, REF_NODEREF, NULL,
+ &err))
+ die(_("Could not write ref %s: %s"), pseudoref, err.buf);
+
+ if (ref_transaction_commit(transaction, &err))
+ die(_("Could not commit ref write %s: %s"), pseudoref, err.buf);
}
static void print_advice(int show_hint, struct replay_opts *opts)
@@ -186,7 +187,7 @@ static void print_advice(int show_hint, struct replay_opts *opts)
* (typically rebase --interactive) wants to take care
* of the commit itself so remove CHERRY_PICK_HEAD
*/
- unlink(git_path("CHERRY_PICK_HEAD"));
+ delete_ref("CHERRY_PICK_HEAD", NULL, REF_NODEREF);
return;
}
@@ -878,8 +879,8 @@ static int rollback_single_pick(void)
{
unsigned char head_sha1[20];
- if (!file_exists(git_path("CHERRY_PICK_HEAD")) &&
- !file_exists(git_path("REVERT_HEAD")))
+ if (read_ref("CHERRY_PICK_HEAD", head_sha1) &&
+ read_ref("REVERT_HEAD", head_sha1))
return error(_("no cherry-pick or revert in progress"));
if (read_ref_full("HEAD", 0, head_sha1, NULL))
return error(_("cannot resolve HEAD"));
@@ -1014,8 +1015,8 @@ static int continue_single_pick(void)
{
const char *argv[] = { "commit", NULL };
- if (!file_exists(git_path("CHERRY_PICK_HEAD")) &&
- !file_exists(git_path("REVERT_HEAD")))
+ if (!ref_exists("CHERRY_PICK_HEAD") &&
+ !ref_exists("REVERT_HEAD"))
return error(_("no cherry-pick or revert in progress"));
return run_command_v_opt(argv, RUN_GIT_CMD);
}
@@ -1030,8 +1031,8 @@ static int sequencer_continue(struct replay_opts *opts)
read_populate_todo(&todo_list, opts);
/* Verify that the conflict has been resolved */
- if (file_exists(git_path("CHERRY_PICK_HEAD")) ||
- file_exists(git_path("REVERT_HEAD"))) {
+ if (ref_exists("CHERRY_PICK_HEAD") ||
+ ref_exists("REVERT_HEAD")) {
int ret = continue_single_pick();
if (ret)
return ret;
diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh
index 9ac7940..f7fd62c 100755
--- a/t/t7509-commit.sh
+++ b/t/t7509-commit.sh
@@ -163,7 +163,7 @@ test_expect_success 'commit respects CHERRY_PICK_HEAD and MERGE_MSG' '
test_tick &&
git commit -am "cherry-pick 1" --author="Cherry <cherry@pick.er>" &&
git tag cherry-pick-head &&
- git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&
+ git update-ref CHERRY_PICK_HEAD $(git rev-parse cherry-pick-head) &&
echo "This is a MERGE_MSG" >.git/MERGE_MSG &&
echo "cherry-pick 1b" >>foo &&
test_tick &&
@@ -178,7 +178,7 @@ test_expect_success 'commit respects CHERRY_PICK_HEAD and MERGE_MSG' '
'
test_expect_success '--reset-author with CHERRY_PICK_HEAD' '
- git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&
+ git update-ref CHERRY_PICK_HEAD $(git rev-parse cherry-pick-head) &&
echo "cherry-pick 2" >>foo &&
test_tick &&
git commit -am "cherry-pick 2" --reset-author &&
diff --git a/wt-status.c b/wt-status.c
index 9c686e6..661c1fb 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1336,8 +1336,7 @@ void wt_status_get_state(struct wt_status_state *state,
state->rebase_in_progress = 1;
state->branch = read_and_strip_branch("rebase-merge/head-name");
state->onto = read_and_strip_branch("rebase-merge/onto");
- } else if (!stat(git_path("CHERRY_PICK_HEAD"), &st) &&
- !get_sha1("CHERRY_PICK_HEAD", sha1)) {
+ } else if (!read_ref("CHERRY_PICK_HEAD", sha1)) {
state->cherry_pick_in_progress = 1;
hashcpy(state->cherry_pick_head_sha1, sha1);
}
@@ -1345,8 +1344,7 @@ void wt_status_get_state(struct wt_status_state *state,
state->bisect_in_progress = 1;
state->branch = read_and_strip_branch("BISECT_START");
}
- if (!stat(git_path("REVERT_HEAD"), &st) &&
- !get_sha1("REVERT_HEAD", sha1)) {
+ if (!read_ref("REVERT_HEAD", sha1)) {
state->revert_in_progress = 1;
hashcpy(state->revert_head_sha1, sha1);
}
--
2.0.4.314.gdbf7a51-twtrsrc
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs
2015-06-25 20:45 ` [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs David Turner
@ 2015-06-25 21:11 ` Junio C Hamano
2015-06-25 22:29 ` David Turner
0 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2015-06-25 21:11 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger
David Turner <dturner@twopensource.com> writes:
> Instead of directly writing to and reading from files in
> $GIT_DIR, use ref API to interact with CHERRY_PICK_HEAD
> and REVERT_HEAD.
>
> Signed-off-by: David Turner <dturner@twopensource.com>
> ---
I may have said this already in the last round, but I cannot shake
off the feeling that this patch is doing two completely unrelated
things at once.
The change to refs.c that introduced the should_autocreate_reflog()
helper (which is a good idea even without any other changes in this
patch) and then using that to commit_ref_update() does not have
anything to do with CHERRY_PICK_HEAD/REVERT_HEAD, does it?
* commit_ref_update() gained a new "flags" parameter, but it does
not seem to be used at all. Why?
* Why is it a good idea to move the "does the log exist or should
we auto-create?" check from log_ref_setup() to
commit_ref_update()?
These are not just unexplained, but does not have anything to do
with using ref API to write and read CHERRY_PICK_HEAD/REVERT_HEAD.
They _might_ be a prerequisite, but it is not clear why. I suspect
that you do not have to touch refs.c at all for the purpose of the
"theme" of the patch explained by the "Subject" line.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs
2015-06-25 21:11 ` Junio C Hamano
@ 2015-06-25 22:29 ` David Turner
0 siblings, 0 replies; 14+ messages in thread
From: David Turner @ 2015-06-25 22:29 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, mhagger
On Thu, 2015-06-25 at 14:11 -0700, Junio C Hamano wrote:
> David Turner <dturner@twopensource.com> writes:
>
> > Instead of directly writing to and reading from files in
> > $GIT_DIR, use ref API to interact with CHERRY_PICK_HEAD
> > and REVERT_HEAD.
> >
> > Signed-off-by: David Turner <dturner@twopensource.com>
> > ---
>
> I may have said this already in the last round, but I cannot shake
> off the feeling that this patch is doing two completely unrelated
> things at once.
>
> The change to refs.c that introduced the should_autocreate_reflog()
> helper (which is a good idea even without any other changes in this
> patch)
I'll break that out into a separate patch when I reroll.
> and then using that to commit_ref_update() does not have
> anything to do with CHERRY_PICK_HEAD/REVERT_HEAD, does it?
I had thought that it did, but some testing shows that it does not (or
at least does not yet). The original series of patches was assembled
out of a long process of making the test suite pass with the alternate
ref backend. I expect that as I rewrite that series, I'll either figure
out what issues these change solved, or remove them. In this case, I'll
split the patch.
> * commit_ref_update() gained a new "flags" parameter, but it does
> not seem to be used at all. Why?
cruft, will remove.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START
2015-06-25 20:45 [PATCH v2 1/6] refs.c: add err arguments to reflog functions David Turner
2015-06-25 20:45 ` [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs David Turner
@ 2015-06-25 20:45 ` David Turner
2015-06-25 20:52 ` Junio C Hamano
2015-06-25 20:45 ` [PATCH v2 4/6] refs: add safe_create_reflog function David Turner
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: David Turner @ 2015-06-25 20:45 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner
This ref needs to go through the refs backend, since some code assumes
that it can be written and read as a ref.
Signed-off-by: David Turner <dturner@twopensource.com>
---
contrib/completion/git-completion.bash | 2 +-
git-bisect.sh | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 93716c4..c4d4d80 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -938,7 +938,7 @@ _git_bisect ()
local subcommands="start bad good skip reset visualize replay log run"
local subcommand="$(__git_find_on_cmdline "$subcommands")"
if [ -z "$subcommand" ]; then
- if [ -f "$(__gitdir)"/BISECT_START ]; then
+ if [ git rev-parse BISECT_START 2>/dev/null ]; then
__gitcomp "$subcommands"
else
__gitcomp "replay start"
diff --git a/git-bisect.sh b/git-bisect.sh
index ae3fec2..8658772 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -166,7 +166,7 @@ bisect_start() {
#
echo "$start_head" >"$GIT_DIR/BISECT_START" && {
test "z$mode" != "z--no-checkout" ||
- git update-ref --no-deref BISECT_HEAD "$start_head"
+ git rev-parse "$start_head" > "$GIT_DIR/BISECT_HEAD"
} &&
git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
eval "$eval true" &&
@@ -399,7 +399,7 @@ bisect_clean_state() {
rm -f "$GIT_DIR/BISECT_RUN" &&
# Cleanup head-name if it got left by an old version of git-bisect
rm -f "$GIT_DIR/head-name" &&
- git update-ref -d --no-deref BISECT_HEAD &&
+ rm -f "$GIT_DIR/BISECT_HEAD" &&
# clean up BISECT_START last
rm -f "$GIT_DIR/BISECT_START"
}
--
2.0.4.314.gdbf7a51-twtrsrc
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START
2015-06-25 20:45 ` [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START David Turner
@ 2015-06-25 20:52 ` Junio C Hamano
2015-06-25 23:21 ` David Turner
0 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2015-06-25 20:52 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger
David Turner <dturner@twopensource.com> writes:
> This ref needs to go through the refs backend, since some code assumes
> that it can be written and read as a ref.
And the reason why BISECT_HEAD cannot be treated as a ref, but must
be treated as a file under $GIT_DIR, is...?
>
> Signed-off-by: David Turner <dturner@twopensource.com>
> ---
> contrib/completion/git-completion.bash | 2 +-
> git-bisect.sh | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 93716c4..c4d4d80 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -938,7 +938,7 @@ _git_bisect ()
> local subcommands="start bad good skip reset visualize replay log run"
> local subcommand="$(__git_find_on_cmdline "$subcommands")"
> if [ -z "$subcommand" ]; then
> - if [ -f "$(__gitdir)"/BISECT_START ]; then
> + if [ git rev-parse BISECT_START 2>/dev/null ]; then
> __gitcomp "$subcommands"
> else
> __gitcomp "replay start"
> diff --git a/git-bisect.sh b/git-bisect.sh
> index ae3fec2..8658772 100755
> --- a/git-bisect.sh
> +++ b/git-bisect.sh
> @@ -166,7 +166,7 @@ bisect_start() {
> #
> echo "$start_head" >"$GIT_DIR/BISECT_START" && {
> test "z$mode" != "z--no-checkout" ||
> - git update-ref --no-deref BISECT_HEAD "$start_head"
> + git rev-parse "$start_head" > "$GIT_DIR/BISECT_HEAD"
> } &&
> git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
> eval "$eval true" &&
> @@ -399,7 +399,7 @@ bisect_clean_state() {
> rm -f "$GIT_DIR/BISECT_RUN" &&
> # Cleanup head-name if it got left by an old version of git-bisect
> rm -f "$GIT_DIR/head-name" &&
> - git update-ref -d --no-deref BISECT_HEAD &&
> + rm -f "$GIT_DIR/BISECT_HEAD" &&
> # clean up BISECT_START last
> rm -f "$GIT_DIR/BISECT_START"
> }
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START
2015-06-25 20:52 ` Junio C Hamano
@ 2015-06-25 23:21 ` David Turner
2015-06-26 0:22 ` David Turner
0 siblings, 1 reply; 14+ messages in thread
From: David Turner @ 2015-06-25 23:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, mhagger
On Thu, 2015-06-25 at 13:52 -0700, Junio C Hamano wrote:
> David Turner <dturner@twopensource.com> writes:
>
> > This ref needs to go through the refs backend, since some code assumes
> > that it can be written and read as a ref.
>
> And the reason why BISECT_HEAD cannot be treated as a ref, but must
> be treated as a file under $GIT_DIR, is...?
After running some tests on the long version of the series, we can and
should move it into the backend; will add a patch to the next reroll
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START
2015-06-25 23:21 ` David Turner
@ 2015-06-26 0:22 ` David Turner
0 siblings, 0 replies; 14+ messages in thread
From: David Turner @ 2015-06-26 0:22 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, mhagger
On Thu, 2015-06-25 at 19:21 -0400, David Turner wrote:
> On Thu, 2015-06-25 at 13:52 -0700, Junio C Hamano wrote:
> > David Turner <dturner@twopensource.com> writes:
> >
> > > This ref needs to go through the refs backend, since some code assumes
> > > that it can be written and read as a ref.
> >
> > And the reason why BISECT_HEAD cannot be treated as a ref, but must
> > be treated as a file under $GIT_DIR, is...?
>
> After running some tests on the long version of the series, we can and
> should move it into the backend; will add a patch to the next reroll
Actually, I've looked into this further. BISECT_START isn't a ref
because it contains the ref name that the bisection started from (not a
symbolic ref). BISECT_HEAD is a ref. Will fix.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 4/6] refs: add safe_create_reflog function
2015-06-25 20:45 [PATCH v2 1/6] refs.c: add err arguments to reflog functions David Turner
2015-06-25 20:45 ` [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs David Turner
2015-06-25 20:45 ` [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START David Turner
@ 2015-06-25 20:45 ` David Turner
2015-06-25 21:02 ` Junio C Hamano
2015-06-25 20:45 ` [PATCH v2 5/6] git-reflog: add create and exists functions David Turner
2015-06-25 20:45 ` [PATCH v2 6/6] git-stash: use git-reflog instead of creating files David Turner
4 siblings, 1 reply; 14+ messages in thread
From: David Turner @ 2015-06-25 20:45 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner
Make log_ref_setup private, and add public safe_create_reflog which
calls log_ref_setup.
In a moment, we will use safe_create_reflog to add reflog creation
commands to git-reflog.
Signed-off-by: David Turner <dturner@twopensource.com>
---
builtin/checkout.c | 4 +---
refs.c | 11 +++++++++++
refs.h | 2 +-
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 93f63d3..b793670 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -621,7 +621,6 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
if (opts->new_orphan_branch) {
if (opts->new_branch_log && !log_all_ref_updates) {
int temp;
- struct strbuf log_file = STRBUF_INIT;
int ret;
const char *ref_name;
struct strbuf err = STRBUF_INIT;
@@ -629,9 +628,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch);
temp = log_all_ref_updates;
log_all_ref_updates = 1;
- ret = log_ref_setup(ref_name, &log_file, &err);
+ ret = safe_create_reflog(ref_name, &err);
log_all_ref_updates = temp;
- strbuf_release(&log_file);
if (ret) {
fprintf(stderr, _("Can not do reflog for '%s'. %s\n"),
opts->new_orphan_branch, err.buf);
diff --git a/refs.c b/refs.c
index de7b5ef..7b02c45 100644
--- a/refs.c
+++ b/refs.c
@@ -3171,6 +3171,17 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf
return 0;
}
+
+int safe_create_reflog(const char *refname, struct strbuf *err)
+{
+ int ret;
+ struct strbuf sb = STRBUF_INIT;
+
+ ret = log_ref_setup(refname, &sb, err);
+ strbuf_release(&sb);
+ return ret;
+}
+
static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
const unsigned char *new_sha1,
const char *committer, const char *msg)
diff --git a/refs.h b/refs.h
index debdefc..2986aac 100644
--- a/refs.h
+++ b/refs.h
@@ -228,7 +228,7 @@ int pack_refs(unsigned int flags);
/*
* Setup reflog before using. Fill in err and return -1 on failure.
*/
-int log_ref_setup(const char *refname, struct strbuf *logfile, struct strbuf *err);
+int safe_create_reflog(const char *refname, struct strbuf *err);
/** Reads log for the value of ref during at_time. **/
extern int read_ref_at(const char *refname, unsigned int flags,
--
2.0.4.314.gdbf7a51-twtrsrc
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 4/6] refs: add safe_create_reflog function
2015-06-25 20:45 ` [PATCH v2 4/6] refs: add safe_create_reflog function David Turner
@ 2015-06-25 21:02 ` Junio C Hamano
0 siblings, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2015-06-25 21:02 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger
David Turner <dturner@twopensource.com> writes:
> Make log_ref_setup private, and add public safe_create_reflog which
> calls log_ref_setup.
>
> In a moment, we will use safe_create_reflog to add reflog creation
> commands to git-reflog.
>
> Signed-off-by: David Turner <dturner@twopensource.com>
> ---
> builtin/checkout.c | 4 +---
> refs.c | 11 +++++++++++
> refs.h | 2 +-
> 3 files changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/builtin/checkout.c b/builtin/checkout.c
> index 93f63d3..b793670 100644
> --- a/builtin/checkout.c
> +++ b/builtin/checkout.c
> @@ -621,7 +621,6 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
> if (opts->new_orphan_branch) {
> if (opts->new_branch_log && !log_all_ref_updates) {
> int temp;
> - struct strbuf log_file = STRBUF_INIT;
> int ret;
> const char *ref_name;
> struct strbuf err = STRBUF_INIT;
> @@ -629,9 +628,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
> ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch);
> temp = log_all_ref_updates;
> log_all_ref_updates = 1;
> - ret = log_ref_setup(ref_name, &log_file, &err);
> + ret = safe_create_reflog(ref_name, &err);
> log_all_ref_updates = temp;
> - strbuf_release(&log_file);
> if (ret) {
> fprintf(stderr, _("Can not do reflog for '%s'. %s\n"),
> opts->new_orphan_branch, err.buf);
Yup, much nicer ;-)
> diff --git a/refs.c b/refs.c
> index de7b5ef..7b02c45 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -3171,6 +3171,17 @@ int log_ref_setup(const char *refname, struct strbuf *sb_logfile, struct strbuf
> return 0;
> }
>
> +
> +int safe_create_reflog(const char *refname, struct strbuf *err)
> +{
> + int ret;
> + struct strbuf sb = STRBUF_INIT;
> +
> + ret = log_ref_setup(refname, &sb, err);
> + strbuf_release(&sb);
> + return ret;
> +}
> +
> static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
> const unsigned char *new_sha1,
> const char *committer, const char *msg)
> diff --git a/refs.h b/refs.h
> index debdefc..2986aac 100644
> --- a/refs.h
> +++ b/refs.h
> @@ -228,7 +228,7 @@ int pack_refs(unsigned int flags);
> /*
> * Setup reflog before using. Fill in err and return -1 on failure.
> */
> -int log_ref_setup(const char *refname, struct strbuf *logfile, struct strbuf *err);
> +int safe_create_reflog(const char *refname, struct strbuf *err);
>
> /** Reads log for the value of ref during at_time. **/
> extern int read_ref_at(const char *refname, unsigned int flags,
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 5/6] git-reflog: add create and exists functions
2015-06-25 20:45 [PATCH v2 1/6] refs.c: add err arguments to reflog functions David Turner
` (2 preceding siblings ...)
2015-06-25 20:45 ` [PATCH v2 4/6] refs: add safe_create_reflog function David Turner
@ 2015-06-25 20:45 ` David Turner
2015-06-25 21:01 ` Junio C Hamano
2015-06-25 21:51 ` David Turner
2015-06-25 20:45 ` [PATCH v2 6/6] git-stash: use git-reflog instead of creating files David Turner
4 siblings, 2 replies; 14+ messages in thread
From: David Turner @ 2015-06-25 20:45 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner
These are necessary because ref backends manage reflogs. In a moment,
we will use these functions to make git stash work with alternate
ref backends.
Signed-off-by: David Turner <dturner@twopensource.com>
---
builtin/reflog.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 78 insertions(+), 1 deletion(-)
diff --git a/builtin/reflog.c b/builtin/reflog.c
index c2eb8ff..a64158d 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -13,6 +13,10 @@ static const char reflog_expire_usage[] =
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>...";
static const char reflog_delete_usage[] =
"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>...";
+static const char reflog_create_usage[] =
+"git reflog create <refs>...";
+static const char reflog_exists_usage[] =
+"git reflog exists <refs>...";
static unsigned long default_reflog_expire;
static unsigned long default_reflog_expire_unreachable;
@@ -699,12 +703,79 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
return status;
}
+static int cmd_reflog_create(int argc, const char **argv, const char *prefix)
+{
+ int i, status = 0, start = 0;
+ struct strbuf err = STRBUF_INIT;
+
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (!strcmp(arg, "--")) {
+ i++;
+ break;
+ }
+ else if (arg[0] == '-')
+ usage(reflog_create_usage);
+ else
+ break;
+ }
+
+ start = i;
+
+ if (argc - start < 1)
+ return error("Nothing to create?");
+
+ for (i = start ; i < argc; i++) {
+ if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL))
+ die("invalid ref format: %s", argv[i]);
+ }
+ for (i = start ; i < argc; i++) {
+ if (safe_create_reflog(argv[i], &err)) {
+ error("could not create reflog %s: %s", argv[i],
+ err.buf);
+ status = 1;
+ strbuf_release(&err);
+ }
+ }
+ return status;
+}
+
+static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
+{
+ int i, status = 0, 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)
+ return error("Nothing to check?");
+
+ for (i = start ; i < argc; i++) {
+ if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL))
+ die("invalid ref format: %s", argv[i]);
+ if (!reflog_exists(argv[i]))
+ status = 1;
+ }
+ return status;
+}
+
/*
* main "reflog"
*/
static const char reflog_usage[] =
-"git reflog [ show | expire | delete ]";
+"git reflog [ show | expire | delete | create | exists ]";
int cmd_reflog(int argc, const char **argv, const char *prefix)
{
@@ -724,5 +795,11 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)
if (!strcmp(argv[1], "delete"))
return cmd_reflog_delete(argc - 1, argv + 1, prefix);
+ if (!strcmp(argv[1], "create"))
+ return cmd_reflog_create(argc - 1, argv + 1, prefix);
+
+ if (!strcmp(argv[1], "exists"))
+ return cmd_reflog_exists(argc - 1, argv + 1, prefix);
+
return cmd_log_reflog(argc, argv, prefix);
}
--
2.0.4.314.gdbf7a51-twtrsrc
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 5/6] git-reflog: add create and exists functions
2015-06-25 20:45 ` [PATCH v2 5/6] git-reflog: add create and exists functions David Turner
@ 2015-06-25 21:01 ` Junio C Hamano
2015-06-25 21:51 ` David Turner
1 sibling, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2015-06-25 21:01 UTC (permalink / raw)
To: David Turner; +Cc: git, mhagger
David Turner <dturner@twopensource.com> writes:
Because...???
> These are necessary because ref backends manage reflogs.
"Because ref backends manage reflogs" may be a good explanation to
implement something as part of ref API, but it does not explain why
that something needs to be implemented in the first place.
> In a moment,
> we will use these functions to make git stash work with alternate
> ref backends.
>
> Signed-off-by: David Turner <dturner@twopensource.com>
> ---
> builtin/reflog.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 78 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/reflog.c b/builtin/reflog.c
> index c2eb8ff..a64158d 100644
> --- a/builtin/reflog.c
> +++ b/builtin/reflog.c
> @@ -13,6 +13,10 @@ static const char reflog_expire_usage[] =
> "git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>...";
> static const char reflog_delete_usage[] =
> "git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>...";
> +static const char reflog_create_usage[] =
> +"git reflog create <refs>...";
It makes sense to take more than one; you may want to prepare more
than one, and you would signal error by exiting with a non-zero
status if any of them failed.
> +static const char reflog_exists_usage[] =
> +"git reflog exists <refs>...";
This is iffy, though. "git reflog exists foo bar" says "all of them
exist" or "some of them exist"? Why is it more useful to implement
"all of them exist"?
Perhaps dropping "..." would be simpler to explain and less
confusing.
> @@ -699,12 +703,79 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
> return status;
> }
>
> +static int cmd_reflog_create(int argc, const char **argv, const char *prefix)
> +{
> + int i, status = 0, start = 0;
> + struct strbuf err = STRBUF_INIT;
> +
> + for (i = 1; i < argc; i++) {
> + const char *arg = argv[i];
> + if (!strcmp(arg, "--")) {
> + i++;
> + break;
> + }
> + else if (arg[0] == '-')
> + usage(reflog_create_usage);
> + else
> + break;
> + }
> +
> + start = i;
> +
> + if (argc - start < 1)
> + return error("Nothing to create?");
> +
> + for (i = start ; i < argc; i++) {
s/start ;/start;/ (everywhere).
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 5/6] git-reflog: add create and exists functions
2015-06-25 20:45 ` [PATCH v2 5/6] git-reflog: add create and exists functions David Turner
2015-06-25 21:01 ` Junio C Hamano
@ 2015-06-25 21:51 ` David Turner
1 sibling, 0 replies; 14+ messages in thread
From: David Turner @ 2015-06-25 21:51 UTC (permalink / raw)
To: git; +Cc: mhagger
On Thu, 2015-06-25 at 16:45 -0400, David Turner wrote:
> +static int cmd_reflog_create(int argc, const char **argv, const char *prefix)
> +{
While revising this patch, I noticed that safe_create_reflog (and this
cmd_reflog_create) only creates reflogs for refs of the form that git
itself would autocreate reflogs for. In other words, it won't create a
reflog for foo, but will create a reflog for refs/heads/foo (even though
that is very likely to already exist).
So I'll fix that when I re-roll.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 6/6] git-stash: use git-reflog instead of creating files
2015-06-25 20:45 [PATCH v2 1/6] refs.c: add err arguments to reflog functions David Turner
` (3 preceding siblings ...)
2015-06-25 20:45 ` [PATCH v2 5/6] git-reflog: add create and exists functions David Turner
@ 2015-06-25 20:45 ` David Turner
4 siblings, 0 replies; 14+ messages in thread
From: David Turner @ 2015-06-25 20:45 UTC (permalink / raw)
To: git, mhagger; +Cc: David Turner
This is in support of alternate ref backends which don't necessarily
store reflogs as files.
Signed-off-by: David Turner <dturner@twopensource.com>
---
git-stash.sh | 4 ++--
refs.c | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/git-stash.sh b/git-stash.sh
index 8e9e2cd..27155bc 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -184,7 +184,7 @@ store_stash () {
fi
# Make sure the reflog for stash is kept.
- : >>"$(git rev-parse --git-path logs/$ref_stash)"
+ git reflog create "$ref_stash"
git update-ref -m "$stash_msg" $ref_stash $w_commit
ret=$?
test $ret != 0 && test -z $quiet &&
@@ -262,7 +262,7 @@ save_stash () {
say "$(gettext "No local changes to save")"
exit 0
fi
- test -f "$(git rev-parse --git-path logs/$ref_stash)" ||
+ git reflog exists $ref_stash ||
clear_stash || die "$(gettext "Cannot initialize stash")"
create_stash "$stash_msg" $untracked
diff --git a/refs.c b/refs.c
index 7b02c45..e11a32b 100644
--- a/refs.c
+++ b/refs.c
@@ -3123,6 +3123,7 @@ static int should_autocreate_reflog(const char *refname)
return starts_with(refname, "refs/heads/") ||
starts_with(refname, "refs/remotes/") ||
starts_with(refname, "refs/notes/") ||
+ !strcmp(refname, "refs/stash") ||
!strcmp(refname, "HEAD");
}
--
2.0.4.314.gdbf7a51-twtrsrc
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-06-26 0:23 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-25 20:45 [PATCH v2 1/6] refs.c: add err arguments to reflog functions David Turner
2015-06-25 20:45 ` [PATCH v2 2/6] cherry-pick: treat CHERRY_PICK_HEAD and REVERT_HEAD as refs David Turner
2015-06-25 21:11 ` Junio C Hamano
2015-06-25 22:29 ` David Turner
2015-06-25 20:45 ` [PATCH v2 3/6] bisect: use refs infrastructure for BISECT_START David Turner
2015-06-25 20:52 ` Junio C Hamano
2015-06-25 23:21 ` David Turner
2015-06-26 0:22 ` David Turner
2015-06-25 20:45 ` [PATCH v2 4/6] refs: add safe_create_reflog function David Turner
2015-06-25 21:02 ` Junio C Hamano
2015-06-25 20:45 ` [PATCH v2 5/6] git-reflog: add create and exists functions David Turner
2015-06-25 21:01 ` Junio C Hamano
2015-06-25 21:51 ` David Turner
2015-06-25 20:45 ` [PATCH v2 6/6] git-stash: use git-reflog instead of creating files David Turner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).