Merge branch 'tg/stash-refresh-index'
"git stash" learned to write refreshed index back to disk. * tg/stash-refresh-index: stash: make sure to write refreshed cache merge: use refresh_and_write_cache factor out refresh_and_write_cache function
This commit is contained in:
16
builtin/am.c
16
builtin/am.c
@ -1071,19 +1071,6 @@ static const char *msgnum(const struct am_state *state)
|
|||||||
return sb.buf;
|
return sb.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh and write index.
|
|
||||||
*/
|
|
||||||
static void refresh_and_write_cache(void)
|
|
||||||
{
|
|
||||||
struct lock_file lock_file = LOCK_INIT;
|
|
||||||
|
|
||||||
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
|
|
||||||
refresh_cache(REFRESH_QUIET);
|
|
||||||
if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
|
|
||||||
die(_("unable to write index file"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dies with a user-friendly message on how to proceed after resolving the
|
* Dies with a user-friendly message on how to proceed after resolving the
|
||||||
* problem. This message can be overridden with state->resolvemsg.
|
* problem. This message can be overridden with state->resolvemsg.
|
||||||
@ -1705,7 +1692,8 @@ static void am_run(struct am_state *state, int resume)
|
|||||||
|
|
||||||
unlink(am_path(state, "dirtyindex"));
|
unlink(am_path(state, "dirtyindex"));
|
||||||
|
|
||||||
refresh_and_write_cache();
|
if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0)
|
||||||
|
die(_("unable to write index file"));
|
||||||
|
|
||||||
if (repo_index_has_changes(the_repository, NULL, &sb)) {
|
if (repo_index_has_changes(the_repository, NULL, &sb)) {
|
||||||
write_state_bool(state, "dirtyindex", 1);
|
write_state_bool(state, "dirtyindex", 1);
|
||||||
|
@ -688,16 +688,13 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
|
|||||||
struct commit_list *remoteheads,
|
struct commit_list *remoteheads,
|
||||||
struct commit *head)
|
struct commit *head)
|
||||||
{
|
{
|
||||||
struct lock_file lock = LOCK_INIT;
|
|
||||||
const char *head_arg = "HEAD";
|
const char *head_arg = "HEAD";
|
||||||
|
|
||||||
hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
|
if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0)
|
||||||
refresh_cache(REFRESH_QUIET);
|
|
||||||
if (write_locked_index(&the_index, &lock,
|
|
||||||
COMMIT_LOCK | SKIP_IF_UNCHANGED))
|
|
||||||
return error(_("Unable to write index."));
|
return error(_("Unable to write index."));
|
||||||
|
|
||||||
if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) {
|
if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) {
|
||||||
|
struct lock_file lock = LOCK_INIT;
|
||||||
int clean, x;
|
int clean, x;
|
||||||
struct commit *result;
|
struct commit *result;
|
||||||
struct commit_list *reversed = NULL;
|
struct commit_list *reversed = NULL;
|
||||||
@ -872,12 +869,8 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
|
|||||||
{
|
{
|
||||||
struct object_id result_tree, result_commit;
|
struct object_id result_tree, result_commit;
|
||||||
struct commit_list *parents, **pptr = &parents;
|
struct commit_list *parents, **pptr = &parents;
|
||||||
struct lock_file lock = LOCK_INIT;
|
|
||||||
|
|
||||||
hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
|
if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0)
|
||||||
refresh_cache(REFRESH_QUIET);
|
|
||||||
if (write_locked_index(&the_index, &lock,
|
|
||||||
COMMIT_LOCK | SKIP_IF_UNCHANGED))
|
|
||||||
return error(_("Unable to write index."));
|
return error(_("Unable to write index."));
|
||||||
|
|
||||||
write_tree_trivial(&result_tree);
|
write_tree_trivial(&result_tree);
|
||||||
|
@ -396,7 +396,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
|
|||||||
const struct object_id *bases[1];
|
const struct object_id *bases[1];
|
||||||
|
|
||||||
read_cache_preload(NULL);
|
read_cache_preload(NULL);
|
||||||
if (refresh_cache(REFRESH_QUIET))
|
if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (write_cache_as_tree(&c_tree, 0, NULL))
|
if (write_cache_as_tree(&c_tree, 0, NULL))
|
||||||
@ -485,7 +485,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (quiet) {
|
if (quiet) {
|
||||||
if (refresh_cache(REFRESH_QUIET))
|
if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
|
||||||
warning("could not refresh index");
|
warning("could not refresh index");
|
||||||
} else {
|
} else {
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
@ -1129,7 +1129,10 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
|
|||||||
prepare_fallback_ident("git stash", "git@stash");
|
prepare_fallback_ident("git stash", "git@stash");
|
||||||
|
|
||||||
read_cache_preload(NULL);
|
read_cache_preload(NULL);
|
||||||
refresh_cache(REFRESH_QUIET);
|
if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (get_oid("HEAD", &info->b_commit)) {
|
if (get_oid("HEAD", &info->b_commit)) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
@ -1290,7 +1293,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
|
|||||||
free(ps_matched);
|
free(ps_matched);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refresh_cache(REFRESH_QUIET)) {
|
if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
18
cache.h
18
cache.h
@ -414,6 +414,7 @@ extern struct index_state the_index;
|
|||||||
#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))
|
#define add_file_to_cache(path, flags) add_file_to_index(&the_index, (path), (flags))
|
||||||
#define chmod_cache_entry(ce, flip) chmod_index_entry(&the_index, (ce), (flip))
|
#define chmod_cache_entry(ce, flip) chmod_index_entry(&the_index, (ce), (flip))
|
||||||
#define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL, NULL)
|
#define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL, NULL)
|
||||||
|
#define refresh_and_write_cache(refresh_flags, write_flags, gentle) repo_refresh_and_write_index(the_repository, (refresh_flags), (write_flags), (gentle), NULL, NULL, NULL)
|
||||||
#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
|
#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
|
||||||
#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
|
#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
|
||||||
#define cache_dir_exists(name, namelen) index_dir_exists(&the_index, (name), (namelen))
|
#define cache_dir_exists(name, namelen) index_dir_exists(&the_index, (name), (namelen))
|
||||||
@ -834,6 +835,23 @@ void fill_stat_cache_info(struct index_state *istate, struct cache_entry *ce, st
|
|||||||
#define REFRESH_IN_PORCELAIN 0x0020 /* user friendly output, not "needs update" */
|
#define REFRESH_IN_PORCELAIN 0x0020 /* user friendly output, not "needs update" */
|
||||||
#define REFRESH_PROGRESS 0x0040 /* show progress bar if stderr is tty */
|
#define REFRESH_PROGRESS 0x0040 /* show progress bar if stderr is tty */
|
||||||
int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
|
int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
|
||||||
|
/*
|
||||||
|
* Refresh the index and write it to disk.
|
||||||
|
*
|
||||||
|
* 'refresh_flags' is passed directly to 'refresh_index()', while
|
||||||
|
* 'COMMIT_LOCK | write_flags' is passed to 'write_locked_index()', so
|
||||||
|
* the lockfile is always either committed or rolled back.
|
||||||
|
*
|
||||||
|
* If 'gentle' is passed, errors locking the index are ignored.
|
||||||
|
*
|
||||||
|
* Return 1 if refreshing the index returns an error, -1 if writing
|
||||||
|
* the index to disk fails, 0 on success.
|
||||||
|
*
|
||||||
|
* Note that if refreshing the index returns an error, we still write
|
||||||
|
* out the index (unless locking fails).
|
||||||
|
*/
|
||||||
|
int repo_refresh_and_write_index(struct repository*, unsigned int refresh_flags, unsigned int write_flags, int gentle, const struct pathspec *, char *seen, const char *header_msg);
|
||||||
|
|
||||||
struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
|
struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
|
||||||
|
|
||||||
void set_alternate_index_output(const char *);
|
void set_alternate_index_output(const char *);
|
||||||
|
21
read-cache.c
21
read-cache.c
@ -1472,6 +1472,27 @@ static void show_file(const char * fmt, const char * name, int in_porcelain,
|
|||||||
printf(fmt, name);
|
printf(fmt, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int repo_refresh_and_write_index(struct repository *repo,
|
||||||
|
unsigned int refresh_flags,
|
||||||
|
unsigned int write_flags,
|
||||||
|
int gentle,
|
||||||
|
const struct pathspec *pathspec,
|
||||||
|
char *seen, const char *header_msg)
|
||||||
|
{
|
||||||
|
struct lock_file lock_file = LOCK_INIT;
|
||||||
|
int fd, ret = 0;
|
||||||
|
|
||||||
|
fd = repo_hold_locked_index(repo, &lock_file, 0);
|
||||||
|
if (!gentle && fd < 0)
|
||||||
|
return -1;
|
||||||
|
if (refresh_index(repo->index, refresh_flags, pathspec, seen, header_msg))
|
||||||
|
ret = 1;
|
||||||
|
if (0 <= fd && write_locked_index(repo->index, &lock_file, COMMIT_LOCK | write_flags))
|
||||||
|
ret = -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int refresh_index(struct index_state *istate, unsigned int flags,
|
int refresh_index(struct index_state *istate, unsigned int flags,
|
||||||
const struct pathspec *pathspec,
|
const struct pathspec *pathspec,
|
||||||
char *seen, const char *header_msg)
|
char *seen, const char *header_msg)
|
||||||
|
@ -1253,4 +1253,20 @@ test_expect_success 'stash --keep-index with file deleted in index does not resu
|
|||||||
test_path_is_missing to-remove
|
test_path_is_missing to-remove
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'stash apply should succeed with unmodified file' '
|
||||||
|
echo base >file &&
|
||||||
|
git add file &&
|
||||||
|
git commit -m base &&
|
||||||
|
|
||||||
|
# now stash a modification
|
||||||
|
echo modified >file &&
|
||||||
|
git stash &&
|
||||||
|
|
||||||
|
# make the file stat dirty
|
||||||
|
cp file other &&
|
||||||
|
mv other file &&
|
||||||
|
|
||||||
|
git stash apply
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user