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:
commit
d75bb73bcf
68
builtin/am.c
68
builtin/am.c
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* at the end.
|
||||
@ -363,7 +384,7 @@ static void write_author_script(const struct am_state *state)
|
||||
sq_quote_buf(&sb, state->author_date);
|
||||
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);
|
||||
}
|
||||
@ -1001,13 +1022,10 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
|
||||
if (state->rebasing)
|
||||
state->threeway = 1;
|
||||
|
||||
write_file(am_path(state, "threeway"), 1, state->threeway ? "t" : "f");
|
||||
|
||||
write_file(am_path(state, "quiet"), 1, state->quiet ? "t" : "f");
|
||||
|
||||
write_file(am_path(state, "sign"), 1, state->signoff ? "t" : "f");
|
||||
|
||||
write_file(am_path(state, "utf8"), 1, state->utf8 ? "t" : "f");
|
||||
write_state_bool(state, "threeway", state->threeway);
|
||||
write_state_bool(state, "quiet", state->quiet);
|
||||
write_state_bool(state, "sign", state->signoff);
|
||||
write_state_bool(state, "utf8", state->utf8);
|
||||
|
||||
switch (state->keep) {
|
||||
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");
|
||||
}
|
||||
|
||||
write_file(am_path(state, "keep"), 1, "%s", str);
|
||||
|
||||
write_file(am_path(state, "messageid"), 1, state->message_id ? "t" : "f");
|
||||
write_state_text(state, "keep", str);
|
||||
write_state_bool(state, "messageid", state->message_id);
|
||||
|
||||
switch (state->scissors) {
|
||||
case SCISSORS_UNSET:
|
||||
@ -1040,24 +1057,23 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
|
||||
default:
|
||||
die("BUG: invalid value for state->scissors");
|
||||
}
|
||||
|
||||
write_file(am_path(state, "scissors"), 1, "%s", str);
|
||||
write_state_text(state, "scissors", str);
|
||||
|
||||
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)
|
||||
write_file(am_path(state, "rebasing"), 1, "%s", "");
|
||||
write_state_text(state, "rebasing", "");
|
||||
else
|
||||
write_file(am_path(state, "applying"), 1, "%s", "");
|
||||
write_state_text(state, "applying", "");
|
||||
|
||||
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)
|
||||
update_ref("am", "ORIG_HEAD", curr_head, NULL, 0,
|
||||
UPDATE_REFS_DIE_ON_ERR);
|
||||
} else {
|
||||
write_file(am_path(state, "abort-safety"), 1, "%s", "");
|
||||
write_state_text(state, "abort-safety", "");
|
||||
if (!state->rebasing)
|
||||
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.
|
||||
*/
|
||||
|
||||
write_file(am_path(state, "next"), 1, "%d", state->cur);
|
||||
|
||||
write_file(am_path(state, "last"), 1, "%d", state->last);
|
||||
write_state_count(state, "next", state->cur);
|
||||
write_state_count(state, "last", state->last);
|
||||
|
||||
strbuf_release(&sb);
|
||||
}
|
||||
@ -1102,12 +1117,12 @@ static void am_next(struct am_state *state)
|
||||
unlink(am_path(state, "original-commit"));
|
||||
|
||||
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
|
||||
write_file(am_path(state, "abort-safety"), 1, "%s", "");
|
||||
write_state_text(state, "abort-safety", "");
|
||||
|
||||
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);
|
||||
|
||||
hashcpy(state->orig_commit, commit_sha1);
|
||||
write_file(am_path(state, "original-commit"), 1, "%s",
|
||||
sha1_to_hex(commit_sha1));
|
||||
write_state_text(state, "original-commit", sha1_to_hex(commit_sha1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1783,7 +1797,7 @@ static void am_run(struct am_state *state, int resume)
|
||||
refresh_and_write_cache();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -776,7 +776,7 @@ static int edit_branch_description(const char *branch_name)
|
||||
" %s\n"
|
||||
"Lines starting with '%c' will be stripped.\n",
|
||||
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);
|
||||
return error(_("could not write branch description template: %s"),
|
||||
strerror(errno));
|
||||
|
@ -378,7 +378,7 @@ static void separate_git_dir(const char *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)
|
||||
|
@ -238,7 +238,7 @@ static int add_worktree(const char *path, const char *refname,
|
||||
* after the preparation is over.
|
||||
*/
|
||||
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);
|
||||
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_addf(&sb, "%s/gitdir", sb_repo.buf);
|
||||
write_file(sb.buf, 1, "%s\n", real_path(sb_git.buf));
|
||||
write_file(sb_git.buf, 1, "gitdir: %s/worktrees/%s\n",
|
||||
write_file(sb.buf, "%s", real_path(sb_git.buf));
|
||||
write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
|
||||
real_path(get_git_common_dir()), name);
|
||||
/*
|
||||
* 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_addf(&sb, "%s/HEAD", sb_repo.buf);
|
||||
write_file(sb.buf, 1, "0000000000000000000000000000000000000000\n");
|
||||
write_file(sb.buf, "0000000000000000000000000000000000000000");
|
||||
strbuf_reset(&sb);
|
||||
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);
|
||||
|
||||
|
5
cache.h
5
cache.h
@ -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));
|
||||
}
|
||||
__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 */
|
||||
extern void setup_pager(void);
|
||||
|
2
daemon.c
2
daemon.c
@ -1376,7 +1376,7 @@ int main(int argc, char **argv)
|
||||
sanitize_stdfds();
|
||||
|
||||
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 */
|
||||
cld_argv = xmalloc(sizeof (char *) * (argc + 2));
|
||||
|
2
setup.c
2
setup.c
@ -404,7 +404,7 @@ static void update_linked_gitdir(const char *gitfile, const char *gitdir)
|
||||
|
||||
strbuf_addf(&path, "%s/gitfile", gitdir);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1033,7 +1033,7 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir)
|
||||
|
||||
/* Update gitfile */
|
||||
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));
|
||||
|
||||
/* Update core.worktree setting */
|
||||
|
@ -291,7 +291,7 @@ static int write_one_ref(const char *name, const struct object_id *oid,
|
||||
|
||||
strbuf_addstr(buf, name);
|
||||
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",
|
||||
buf->buf, strerror(errno));
|
||||
strbuf_setlen(buf, len);
|
||||
|
29
wrapper.c
29
wrapper.c
@ -621,19 +621,18 @@ char *xgetcwd(void)
|
||||
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;
|
||||
va_list params;
|
||||
int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd < 0) {
|
||||
if (fatal)
|
||||
die_errno(_("could not open %s for writing"), path);
|
||||
return -1;
|
||||
}
|
||||
va_start(params, fmt);
|
||||
strbuf_vaddf(&sb, fmt, params);
|
||||
va_end(params);
|
||||
strbuf_complete_line(&sb);
|
||||
if (write_in_full(fd, sb.buf, sb.len) != sb.len) {
|
||||
int err = errno;
|
||||
close(fd);
|
||||
@ -652,6 +651,28 @@ int write_file(const char *path, int fatal, const char *fmt, ...)
|
||||
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)
|
||||
{
|
||||
poll(NULL, 0, millisec);
|
||||
|
Loading…
Reference in New Issue
Block a user