From: Junio C Hamano <gitster@pobox.com>
To: Ronnie Sahlberg <sahlberg@google.com>
Cc: Duy Nguyen <pclouds@gmail.com>,
Git Mailing List <git@vger.kernel.org>,
Jonathan Nieder <jrnieder@gmail.com>
Subject: Re: What's cooking in git.git (Sep 2014, #01; Tue, 2)
Date: Thu, 04 Sep 2014 10:25:43 -0700 [thread overview]
Message-ID: <xmqqa96fuwko.fsf@gitster.dls.corp.google.com> (raw)
In-Reply-To: <xmqqmwafux3y.fsf@gitster.dls.corp.google.com> (Junio C. Hamano's message of "Thu, 04 Sep 2014 10:14:09 -0700")
Junio C Hamano <gitster@pobox.com> writes:
> You can see the interactions by checking
>
> $ git show 'pu^{/^Merge branch .nd/multi}' refs.c
Here is how it may look like.
Merge branch 'nd/multiple-work-trees' into pu
diff --cc refs.c
index b50b329,00b2312..f04d934
--- a/refs.c
+++ b/refs.c
@@@ -1359,34 -1533,33 +1359,38 @@@ static const char *handle_missing_loose
}
}
-const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int reading, int *flag)
+/* This function needs to return a meaningful errno on failure */
+const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int flags, int *ref_flag)
{
+ struct strbuf sb_path = STRBUF_INIT;
int depth = MAXDEPTH;
ssize_t len;
char buffer[256];
static char refname_buffer[256];
+ const char *ret;
- if (flag)
- *flag = 0;
+ if (ref_flag)
+ *ref_flag = 0;
- if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
+ if (!(flags & RESOLVE_REF_ALLOW_BAD_NAME) &&
+ check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
+ errno = EINVAL;
return NULL;
-
+ }
for (;;) {
- char path[PATH_MAX];
+ const char *path;
struct stat st;
char *buf;
int fd;
- if (--depth < 0)
+ if (--depth < 0) {
+ errno = ELOOP;
- return NULL;
+ goto fail;
+ }
- git_snpath(path, sizeof(path), "%s", refname);
+ strbuf_reset(&sb_path);
+ strbuf_git_path(&sb_path, "%s", refname);
+ path = sb_path.buf;
/*
* We might have to loop back here to avoid a race
@@@ -1400,11 -1573,11 +1404,12 @@@
stat_ref:
if (lstat(path, &st) < 0) {
if (errno == ENOENT)
- return handle_missing_loose_ref(refname, sha1,
+ ret = handle_missing_loose_ref(refname, sha1,
- reading, flag);
+ flags & RESOLVE_REF_READING,
+ ref_flag);
else
- return NULL;
+ ret = NULL;
+ goto done;
}
/* Follow "normalized" - ie "refs/.." symlinks by hand */
@@@ -1444,16 -1617,13 +1449,17 @@@
/* inconsistent with lstat; retry */
goto stat_ref;
else
- return NULL;
+ goto fail;
}
+
len = read_in_full(fd, buffer, sizeof(buffer)-1);
- close(fd);
- if (len < 0)
+ if (len < 0) {
+ int save_errno = errno;
+ close(fd);
+ errno = save_errno;
- return NULL;
+ goto fail;
+ }
+ close(fd);
while (len && isspace(buffer[len-1]))
len--;
buffer[len] = '\0';
@@@ -1468,31 -1638,35 +1474,37 @@@
*/
if (get_sha1_hex(buffer, sha1) ||
(buffer[40] != '\0' && !isspace(buffer[40]))) {
- if (flag)
- *flag |= REF_ISBROKEN;
+ if (ref_flag)
+ *ref_flag |= REF_ISBROKEN;
+ errno = EINVAL;
- return NULL;
+ goto fail;
}
- return refname;
+ ret = refname;
+ goto done;
}
- if (flag)
- *flag |= REF_ISSYMREF;
+ if (ref_flag)
+ *ref_flag |= REF_ISSYMREF;
buf = buffer + 4;
while (isspace(*buf))
buf++;
if (check_refname_format(buf, REFNAME_ALLOW_ONELEVEL)) {
- if (flag)
- *flag |= REF_ISBROKEN;
+ if (ref_flag)
+ *ref_flag |= REF_ISBROKEN;
+ errno = EINVAL;
- return NULL;
+ goto fail;
}
refname = strcpy(refname_buffer, buf);
}
+ fail:
+ ret = NULL;
+ done:
+ strbuf_release(&sb_path);
+ return ret;
}
-char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int *flag)
+char *resolve_refdup(const char *ref, unsigned char *sha1, int flags, int *ref_flag)
{
- const char *ret = resolve_ref_unsafe(ref, sha1, reading, flag);
+ const char *ret = resolve_ref_unsafe(ref, sha1, flags, ref_flag);
return ret ? xstrdup(ret) : NULL;
}
@@@ -2106,16 -2263,11 +2118,16 @@@ int dwim_log(const char *str, int len,
return logs_found;
}
+/*
+ * Locks a "refs/" ref returning the lock on success and NULL on failure.
+ * On failure errno is set to something meaningful.
+ */
static struct ref_lock *lock_ref_sha1_basic(const char *refname,
const unsigned char *old_sha1,
- int flags, int *type_p)
+ int flags, int *type_p,
+ const char **skip, int skipnum)
{
- char *ref_file;
+ const char *ref_file;
const char *orig_refname = refname;
struct ref_lock *lock;
int last_errno = 0;
@@@ -2750,52 -2952,41 +2762,57 @@@ static int copy_msg(char *buf, const ch
return cp - buf;
}
-int log_ref_setup(const char *refname, struct strbuf *logfile)
+/* This function must set a meaningful errno on failure */
+int create_reflog(const char *refname)
{
int logfd, oflags = O_APPEND | O_WRONLY;
- char logfile[PATH_MAX];
-
- git_snpath(logfile, sizeof(logfile), "logs/%s", refname);
- if (starts_with(refname, "refs/heads/") ||
- starts_with(refname, "refs/remotes/") ||
- starts_with(refname, "refs/notes/") ||
- !strcmp(refname, "HEAD")) {
- if (safe_create_leading_directories(logfile) < 0) {
++ struct strbuf logfile = STRBUF_INIT;
+
- strbuf_git_path(logfile, "logs/%s", refname);
++ strbuf_git_path(&logfile, "logs/%s", refname);
+ if (log_all_ref_updates &&
+ (starts_with(refname, "refs/heads/") ||
+ starts_with(refname, "refs/remotes/") ||
+ starts_with(refname, "refs/notes/") ||
+ !strcmp(refname, "HEAD"))) {
- if (safe_create_leading_directories(logfile->buf) < 0)
- return error("unable to create directory for %s",
- logfile->buf);
++ if (safe_create_leading_directories(logfile.buf) < 0) {
+ int save_errno = errno;
- error("unable to create directory for %s", logfile);
++ error("unable to create directory for %s", logfile.buf);
++ strbuf_release(&logfile);
+ errno = save_errno;
+ return -1;
+ }
oflags |= O_CREAT;
}
- logfd = open(logfile, oflags, 0666);
- logfd = open(logfile->buf, oflags, 0666);
++ logfd = open(logfile.buf, oflags, 0666);
if (logfd < 0) {
if (!(oflags & O_CREAT) && errno == ENOENT)
return 0;
if ((oflags & O_CREAT) && errno == EISDIR) {
- if (remove_empty_directories(logfile)) {
- if (remove_empty_directories(logfile->buf)) {
- return error("There are still logs under '%s'",
- logfile->buf);
++ if (remove_empty_directories(logfile.buf)) {
+ int save_errno = errno;
+ error("There are still logs under '%s'",
- logfile);
++ logfile.buf);
++ strbuf_release(&logfile);
+ errno = save_errno;
+ return -1;
}
- logfd = open(logfile, oflags, 0666);
- logfd = open(logfile->buf, oflags, 0666);
++ logfd = open(logfile.buf, oflags, 0666);
}
- if (logfd < 0)
- return error("Unable to append to %s: %s",
- logfile->buf, strerror(errno));
+ if (logfd < 0) {
+ int save_errno = errno;
- error("Unable to append to %s: %s", logfile,
++ error("Unable to append to %s: %s", logfile.buf,
+ strerror(errno));
++ strbuf_release(&logfile);
+ errno = save_errno;
+ return -1;
+ }
}
- adjust_shared_perm(logfile);
- adjust_shared_perm(logfile->buf);
++ adjust_shared_perm(logfile.buf);
++ strbuf_release(&logfile);
close(logfd);
return 0;
}
@@@ -2817,54 -3023,18 +2834,58 @@@ static int log_ref_write_fd(int fd, con
committer);
if (msglen)
len += copy_msg(logrec + len - 1, msg) - 1;
- written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;
+
+ written = len <= maxlen ? write_in_full(fd, logrec, len) : -1;
free(logrec);
- if (close(logfd) != 0 || written != len) {
- error("Unable to append to %s", log_file);
- result = -1;
- }
-done:
- strbuf_release(&sb_log_file);
- return result;
+ if (written != len)
+ 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)
+{
+ int logfd, result = 0, oflags = O_APPEND | O_WRONLY;
- char log_file[PATH_MAX];
++ struct strbuf logfile = STRBUF_INIT;
++ int status = 0;
+
+ if (log_all_ref_updates < 0)
+ log_all_ref_updates = !is_bare_repository();
+
+ if (log_all_ref_updates && !reflog_exists(refname))
+ result = create_reflog(refname);
+
+ if (result)
+ return result;
+
- git_snpath(log_file, sizeof(log_file), "logs/%s", refname);
++ strbuf_git_path(&logfile, "logs/%s", refname);
+
- logfd = open(log_file, oflags);
++ logfd = open(logfile.buf, oflags);
+ if (logfd < 0)
- return 0;
++ goto fini;
+ 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);
++ error("Unable to append to %s", logfile.buf);
+ errno = save_errno;
- return -1;
++ status = -1;
++ goto fini;
+ }
+ if (close(logfd)) {
+ int save_errno = errno;
- error("Unable to append to %s", log_file);
++ error("Unable to append to %s", logfile.buf);
+ errno = save_errno;
- return -1;
++ status = -1;
+ }
- return 0;
++fini:
++ strbuf_release(&logfile);
++ return status;
}
-static int is_branch(const char *refname)
+int is_branch(const char *refname)
{
return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
}
next prev parent reply other threads:[~2014-09-04 17:26 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-02 22:06 What's cooking in git.git (Sep 2014, #01; Tue, 2) Junio C Hamano
2014-09-03 6:27 ` Johannes Sixt
2014-09-03 18:45 ` Torsten Bögershausen
2014-09-03 19:18 ` Junio C Hamano
2014-09-03 19:30 ` Keller, Jacob E
2014-09-04 13:46 ` Duy Nguyen
2014-09-04 16:51 ` Junio C Hamano
2014-09-04 17:14 ` Junio C Hamano
2014-09-04 17:25 ` Junio C Hamano [this message]
2014-09-05 1:18 ` Duy Nguyen
2014-09-05 0:47 ` Duy Nguyen
2015-03-26 13:46 ` Tommy38
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xmqqa96fuwko.fsf@gitster.dls.corp.google.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=jrnieder@gmail.com \
--cc=pclouds@gmail.com \
--cc=sahlberg@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.