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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
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));
|
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);
|
||||||
|
2
daemon.c
2
daemon.c
@ -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));
|
||||||
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
29
wrapper.c
29
wrapper.c
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user