Merge branch 'jc/am-state-fix'

Recent reimplementation of "git am" changed the format of state
files kept in $GIT_DIR/rebase-apply/ without meaning to do so,
primarily because write_file() API was cumbersome to use and it was
easy to mistakenly make text files with incomplete lines.  Update
write_file() interface to make it harder to misuse.

* jc/am-state-fix:
  write_file(): drop caller-supplied LF from calls to create a one-liner file
  write_file_v(): do not leave incomplete line at the end
  write_file(): drop "fatal" parameter
  builtin/am: make sure state files are text
  builtin/am: introduce write_state_*() helper functions
This commit is contained in:
Junio C Hamano 2015-08-31 15:39:01 -07:00
commit d75bb73bcf
10 changed files with 80 additions and 44 deletions

View File

@ -194,6 +194,27 @@ static inline const char *am_path(const struct am_state *state, const char *path
return mkpath("%s/%s", state->dir, path); return mkpath("%s/%s", state->dir, path);
} }
/**
* For convenience to call write_file()
*/
static int write_state_text(const struct am_state *state,
const char *name, const char *string)
{
return write_file(am_path(state, name), "%s", string);
}
static int write_state_count(const struct am_state *state,
const char *name, int value)
{
return write_file(am_path(state, name), "%d", value);
}
static int write_state_bool(const struct am_state *state,
const char *name, int value)
{
return write_state_text(state, name, value ? "t" : "f");
}
/** /**
* If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline
* at the end. * at the end.
@ -363,7 +384,7 @@ static void write_author_script(const struct am_state *state)
sq_quote_buf(&sb, state->author_date); sq_quote_buf(&sb, state->author_date);
strbuf_addch(&sb, '\n'); strbuf_addch(&sb, '\n');
write_file(am_path(state, "author-script"), 1, "%s", sb.buf); write_state_text(state, "author-script", sb.buf);
strbuf_release(&sb); strbuf_release(&sb);
} }
@ -1001,13 +1022,10 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
if (state->rebasing) if (state->rebasing)
state->threeway = 1; state->threeway = 1;
write_file(am_path(state, "threeway"), 1, state->threeway ? "t" : "f"); write_state_bool(state, "threeway", state->threeway);
write_state_bool(state, "quiet", state->quiet);
write_file(am_path(state, "quiet"), 1, state->quiet ? "t" : "f"); write_state_bool(state, "sign", state->signoff);
write_state_bool(state, "utf8", state->utf8);
write_file(am_path(state, "sign"), 1, state->signoff ? "t" : "f");
write_file(am_path(state, "utf8"), 1, state->utf8 ? "t" : "f");
switch (state->keep) { switch (state->keep) {
case KEEP_FALSE: case KEEP_FALSE:
@ -1023,9 +1041,8 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
die("BUG: invalid value for state->keep"); die("BUG: invalid value for state->keep");
} }
write_file(am_path(state, "keep"), 1, "%s", str); write_state_text(state, "keep", str);
write_state_bool(state, "messageid", state->message_id);
write_file(am_path(state, "messageid"), 1, state->message_id ? "t" : "f");
switch (state->scissors) { switch (state->scissors) {
case SCISSORS_UNSET: case SCISSORS_UNSET:
@ -1040,24 +1057,23 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
default: default:
die("BUG: invalid value for state->scissors"); die("BUG: invalid value for state->scissors");
} }
write_state_text(state, "scissors", str);
write_file(am_path(state, "scissors"), 1, "%s", str);
sq_quote_argv(&sb, state->git_apply_opts.argv, 0); sq_quote_argv(&sb, state->git_apply_opts.argv, 0);
write_file(am_path(state, "apply-opt"), 1, "%s", sb.buf); write_state_text(state, "apply-opt", sb.buf);
if (state->rebasing) if (state->rebasing)
write_file(am_path(state, "rebasing"), 1, "%s", ""); write_state_text(state, "rebasing", "");
else else
write_file(am_path(state, "applying"), 1, "%s", ""); write_state_text(state, "applying", "");
if (!get_sha1("HEAD", curr_head)) { if (!get_sha1("HEAD", curr_head)) {
write_file(am_path(state, "abort-safety"), 1, "%s", sha1_to_hex(curr_head)); write_state_text(state, "abort-safety", sha1_to_hex(curr_head));
if (!state->rebasing) if (!state->rebasing)
update_ref("am", "ORIG_HEAD", curr_head, NULL, 0, update_ref("am", "ORIG_HEAD", curr_head, NULL, 0,
UPDATE_REFS_DIE_ON_ERR); UPDATE_REFS_DIE_ON_ERR);
} else { } else {
write_file(am_path(state, "abort-safety"), 1, "%s", ""); write_state_text(state, "abort-safety", "");
if (!state->rebasing) if (!state->rebasing)
delete_ref("ORIG_HEAD", NULL, 0); delete_ref("ORIG_HEAD", NULL, 0);
} }
@ -1067,9 +1083,8 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
* session is in progress, they should be written last. * session is in progress, they should be written last.
*/ */
write_file(am_path(state, "next"), 1, "%d", state->cur); write_state_count(state, "next", state->cur);
write_state_count(state, "last", state->last);
write_file(am_path(state, "last"), 1, "%d", state->last);
strbuf_release(&sb); strbuf_release(&sb);
} }
@ -1102,12 +1117,12 @@ static void am_next(struct am_state *state)
unlink(am_path(state, "original-commit")); unlink(am_path(state, "original-commit"));
if (!get_sha1("HEAD", head)) if (!get_sha1("HEAD", head))
write_file(am_path(state, "abort-safety"), 1, "%s", sha1_to_hex(head)); write_state_text(state, "abort-safety", sha1_to_hex(head));
else else
write_file(am_path(state, "abort-safety"), 1, "%s", ""); write_state_text(state, "abort-safety", "");
state->cur++; state->cur++;
write_file(am_path(state, "next"), 1, "%d", state->cur); write_state_count(state, "next", state->cur);
} }
/** /**
@ -1480,8 +1495,7 @@ static int parse_mail_rebase(struct am_state *state, const char *mail)
write_commit_patch(state, commit); write_commit_patch(state, commit);
hashcpy(state->orig_commit, commit_sha1); hashcpy(state->orig_commit, commit_sha1);
write_file(am_path(state, "original-commit"), 1, "%s", write_state_text(state, "original-commit", sha1_to_hex(commit_sha1));
sha1_to_hex(commit_sha1));
return 0; return 0;
} }
@ -1783,7 +1797,7 @@ static void am_run(struct am_state *state, int resume)
refresh_and_write_cache(); refresh_and_write_cache();
if (index_has_changes(&sb)) { if (index_has_changes(&sb)) {
write_file(am_path(state, "dirtyindex"), 1, "t"); write_state_bool(state, "dirtyindex", 1);
die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf); die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf);
} }

View File

@ -776,7 +776,7 @@ static int edit_branch_description(const char *branch_name)
" %s\n" " %s\n"
"Lines starting with '%c' will be stripped.\n", "Lines starting with '%c' will be stripped.\n",
branch_name, comment_line_char); branch_name, comment_line_char);
if (write_file(git_path(edit_description), 0, "%s", buf.buf)) { if (write_file_gently(git_path(edit_description), "%s", buf.buf)) {
strbuf_release(&buf); strbuf_release(&buf);
return error(_("could not write branch description template: %s"), return error(_("could not write branch description template: %s"),
strerror(errno)); strerror(errno));

View File

@ -378,7 +378,7 @@ static void separate_git_dir(const char *git_dir)
die_errno(_("unable to move %s to %s"), src, git_dir); die_errno(_("unable to move %s to %s"), src, git_dir);
} }
write_file(git_link, 1, "gitdir: %s\n", git_dir); write_file(git_link, "gitdir: %s", git_dir);
} }
int init_db(const char *template_dir, unsigned int flags) int init_db(const char *template_dir, unsigned int flags)

View File

@ -238,7 +238,7 @@ static int add_worktree(const char *path, const char *refname,
* after the preparation is over. * after the preparation is over.
*/ */
strbuf_addf(&sb, "%s/locked", sb_repo.buf); strbuf_addf(&sb, "%s/locked", sb_repo.buf);
write_file(sb.buf, 1, "initializing\n"); write_file(sb.buf, "initializing");
strbuf_addf(&sb_git, "%s/.git", path); strbuf_addf(&sb_git, "%s/.git", path);
if (safe_create_leading_directories_const(sb_git.buf)) if (safe_create_leading_directories_const(sb_git.buf))
@ -248,8 +248,8 @@ static int add_worktree(const char *path, const char *refname,
strbuf_reset(&sb); strbuf_reset(&sb);
strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
write_file(sb.buf, 1, "%s\n", real_path(sb_git.buf)); write_file(sb.buf, "%s", real_path(sb_git.buf));
write_file(sb_git.buf, 1, "gitdir: %s/worktrees/%s\n", write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
real_path(get_git_common_dir()), name); real_path(get_git_common_dir()), name);
/* /*
* This is to keep resolve_ref() happy. We need a valid HEAD * This is to keep resolve_ref() happy. We need a valid HEAD
@ -260,10 +260,10 @@ static int add_worktree(const char *path, const char *refname,
*/ */
strbuf_reset(&sb); strbuf_reset(&sb);
strbuf_addf(&sb, "%s/HEAD", sb_repo.buf); strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
write_file(sb.buf, 1, "0000000000000000000000000000000000000000\n"); write_file(sb.buf, "0000000000000000000000000000000000000000");
strbuf_reset(&sb); strbuf_reset(&sb);
strbuf_addf(&sb, "%s/commondir", sb_repo.buf); strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
write_file(sb.buf, 1, "../..\n"); write_file(sb.buf, "../..");
fprintf_ln(stderr, _("Preparing %s (identifier %s)"), path, name); fprintf_ln(stderr, _("Preparing %s (identifier %s)"), path, name);

View File

@ -1577,8 +1577,9 @@ static inline ssize_t write_str_in_full(int fd, const char *str)
{ {
return write_in_full(fd, str, strlen(str)); return write_in_full(fd, str, strlen(str));
} }
__attribute__((format (printf, 3, 4)))
extern int write_file(const char *path, int fatal, const char *fmt, ...); extern int write_file(const char *path, const char *fmt, ...);
extern int write_file_gently(const char *path, const char *fmt, ...);
/* pager.c */ /* pager.c */
extern void setup_pager(void); extern void setup_pager(void);

View File

@ -1376,7 +1376,7 @@ int main(int argc, char **argv)
sanitize_stdfds(); sanitize_stdfds();
if (pid_file) if (pid_file)
write_file(pid_file, 1, "%"PRIuMAX"\n", (uintmax_t) getpid()); write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid());
/* prepare argv for serving-processes */ /* prepare argv for serving-processes */
cld_argv = xmalloc(sizeof (char *) * (argc + 2)); cld_argv = xmalloc(sizeof (char *) * (argc + 2));

View File

@ -404,7 +404,7 @@ static void update_linked_gitdir(const char *gitfile, const char *gitdir)
strbuf_addf(&path, "%s/gitfile", gitdir); strbuf_addf(&path, "%s/gitfile", gitdir);
if (stat(path.buf, &st) || st.st_mtime + 24 * 3600 < time(NULL)) if (stat(path.buf, &st) || st.st_mtime + 24 * 3600 < time(NULL))
write_file(path.buf, 0, "%s\n", gitfile); write_file_gently(path.buf, "%s", gitfile);
strbuf_release(&path); strbuf_release(&path);
} }

View File

@ -1033,7 +1033,7 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir)
/* Update gitfile */ /* Update gitfile */
strbuf_addf(&file_name, "%s/.git", work_tree); strbuf_addf(&file_name, "%s/.git", work_tree);
write_file(file_name.buf, 1, "gitdir: %s\n", write_file(file_name.buf, "gitdir: %s",
relative_path(git_dir, real_work_tree, &rel_path)); relative_path(git_dir, real_work_tree, &rel_path));
/* Update core.worktree setting */ /* Update core.worktree setting */

View File

@ -291,7 +291,7 @@ static int write_one_ref(const char *name, const struct object_id *oid,
strbuf_addstr(buf, name); strbuf_addstr(buf, name);
if (safe_create_leading_directories(buf->buf) || if (safe_create_leading_directories(buf->buf) ||
write_file(buf->buf, 0, "%s\n", oid_to_hex(oid))) write_file_gently(buf->buf, "%s", oid_to_hex(oid)))
return error("problems writing temporary file %s: %s", return error("problems writing temporary file %s: %s",
buf->buf, strerror(errno)); buf->buf, strerror(errno));
strbuf_setlen(buf, len); strbuf_setlen(buf, len);

View File

@ -621,19 +621,18 @@ char *xgetcwd(void)
return strbuf_detach(&sb, NULL); return strbuf_detach(&sb, NULL);
} }
int write_file(const char *path, int fatal, const char *fmt, ...) static int write_file_v(const char *path, int fatal,
const char *fmt, va_list params)
{ {
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
va_list params;
int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666); int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd < 0) { if (fd < 0) {
if (fatal) if (fatal)
die_errno(_("could not open %s for writing"), path); die_errno(_("could not open %s for writing"), path);
return -1; return -1;
} }
va_start(params, fmt);
strbuf_vaddf(&sb, fmt, params); strbuf_vaddf(&sb, fmt, params);
va_end(params); strbuf_complete_line(&sb);
if (write_in_full(fd, sb.buf, sb.len) != sb.len) { if (write_in_full(fd, sb.buf, sb.len) != sb.len) {
int err = errno; int err = errno;
close(fd); close(fd);
@ -652,6 +651,28 @@ int write_file(const char *path, int fatal, const char *fmt, ...)
return 0; return 0;
} }
int write_file(const char *path, const char *fmt, ...)
{
int status;
va_list params;
va_start(params, fmt);
status = write_file_v(path, 1, fmt, params);
va_end(params);
return status;
}
int write_file_gently(const char *path, const char *fmt, ...)
{
int status;
va_list params;
va_start(params, fmt);
status = write_file_v(path, 0, fmt, params);
va_end(params);
return status;
}
void sleep_millisec(int millisec) void sleep_millisec(int millisec)
{ {
poll(NULL, 0, millisec); poll(NULL, 0, millisec);