Skip to content

Commit

Permalink
Merge branch 'dg/local-mod-error-messages'
Browse files Browse the repository at this point in the history
* dg/local-mod-error-messages:
  t7609: test merge and checkout error messages
  unpack_trees: group error messages by type
  merge-recursive: distinguish "removed" and "overwritten" messages
  merge-recursive: porcelain messages for checkout
  Turn unpack_trees_options.msgs into an array + enum

Conflicts:
	t/t3400-rebase.sh
  • Loading branch information
Junio C Hamano committed Aug 22, 2010
2 parents a0b6a9d + e935e62 commit 2eb5469
Show file tree
Hide file tree
Showing 13 changed files with 340 additions and 81 deletions.
2 changes: 2 additions & 0 deletions Documentation/technical/api-tree-walking.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ information.

* `data` can be anything the `fn` callback would want to use.

* `show_all_errors` tells whether to stop at the first error or not.

Initializing
------------

Expand Down
3 changes: 2 additions & 1 deletion builtin/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ static int merge_working_tree(struct checkout_opts *opts,
topts.src_index = &the_index;
topts.dst_index = &the_index;

topts.msgs.not_uptodate_file = "You have local changes to '%s'; cannot switch branches.";
set_porcelain_error_msgs(topts.msgs, "checkout");

refresh_cache(REFRESH_QUIET);

Expand All @@ -395,6 +395,7 @@ static int merge_working_tree(struct checkout_opts *opts,
topts.dir = xcalloc(1, sizeof(*topts.dir));
topts.dir->flags |= DIR_SHOW_IGNORED;
topts.dir->exclude_per_dir = ".gitignore";
topts.show_all_errors = 1;
tree = parse_tree_indirect(old->commit ?
old->commit->object.sha1 :
(unsigned char *)EMPTY_TREE_SHA1_BIN);
Expand Down
3 changes: 2 additions & 1 deletion builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,8 @@ int checkout_fast_forward(const unsigned char *head, const unsigned char *remote
opts.verbose_update = 1;
opts.merge = 1;
opts.fn = twoway_merge;
opts.msgs = get_porcelain_error_msgs();
opts.show_all_errors = 1;
set_porcelain_error_msgs(opts.msgs, "merge");

trees[nr_trees] = parse_tree_indirect(head);
if (!trees[nr_trees++])
Expand Down
62 changes: 42 additions & 20 deletions merge-recursive.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ static int git_merge_trees(int index_only,
opts.fn = threeway_merge;
opts.src_index = &the_index;
opts.dst_index = &the_index;
opts.msgs = get_porcelain_error_msgs();
set_porcelain_error_msgs(opts.msgs, "merge");

init_tree_desc_from_tree(t+0, common);
init_tree_desc_from_tree(t+1, head);
Expand Down Expand Up @@ -1173,26 +1173,48 @@ static int process_entry(struct merge_options *o,
return clean_merge;
}

struct unpack_trees_error_msgs get_porcelain_error_msgs(void)
void set_porcelain_error_msgs(const char **msgs, const char *cmd)
{
struct unpack_trees_error_msgs msgs = {
/* would_overwrite */
"Your local changes to '%s' would be overwritten by merge. Aborting.",
/* not_uptodate_file */
"Your local changes to '%s' would be overwritten by merge. Aborting.",
/* not_uptodate_dir */
"Updating '%s' would lose untracked files in it. Aborting.",
/* would_lose_untracked */
"Untracked working tree file '%s' would be %s by merge. Aborting",
/* bind_overlap -- will not happen here */
NULL,
};
if (advice_commit_before_merge) {
msgs.would_overwrite = msgs.not_uptodate_file =
"Your local changes to '%s' would be overwritten by merge. Aborting.\n"
"Please, commit your changes or stash them before you can merge.";
}
return msgs;
const char *msg;
char *tmp;
const char *cmd2 = strcmp(cmd, "checkout") ? cmd : "switch branches";
if (advice_commit_before_merge)
msg = "Your local changes to the following files would be overwritten by %s:\n%%s"
"Please, commit your changes or stash them before you can %s.";
else
msg = "Your local changes to the following files would be overwritten by %s:\n%%s";
tmp = xmalloc(strlen(msg) + strlen(cmd) + strlen(cmd2) - 2);
sprintf(tmp, msg, cmd, cmd2);
msgs[ERROR_WOULD_OVERWRITE] = tmp;
msgs[ERROR_NOT_UPTODATE_FILE] = tmp;

msgs[ERROR_NOT_UPTODATE_DIR] =
"Updating the following directories would lose untracked files in it:\n%s";

if (advice_commit_before_merge)
msg = "The following untracked working tree files would be %s by %s:\n%%s"
"Please move or remove them before you can %s.";
else
msg = "The following untracked working tree files would be %s by %s:\n%%s";
tmp = xmalloc(strlen(msg) + strlen(cmd) + strlen("removed") + strlen(cmd2) - 4);
sprintf(tmp, msg, "removed", cmd, cmd2);
msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] = tmp;
tmp = xmalloc(strlen(msg) + strlen(cmd) + strlen("overwritten") + strlen(cmd2) - 4);
sprintf(tmp, msg, "overwritten", cmd, cmd2);
msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] = tmp;

/*
* Special case: ERROR_BIND_OVERLAP refers to a pair of paths, we
* cannot easily display it as a list.
*/
msgs[ERROR_BIND_OVERLAP] = "Entry '%s' overlaps with '%s'. Cannot bind.";

msgs[ERROR_SPARSE_NOT_UPTODATE_FILE] =
"Cannot update sparse checkout: the following entries are not up-to-date:\n%s";
msgs[ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN] =
"The following Working tree files would be overwritten by sparse checkout update:\n%s";
msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] =
"The following Working tree files would be removed by sparse checkout update:\n%s";
}

int merge_trees(struct merge_options *o,
Expand Down
7 changes: 5 additions & 2 deletions merge-recursive.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ struct merge_options {
struct string_list current_directory_set;
};

/* Return a list of user-friendly error messages to be used by merge */
struct unpack_trees_error_msgs get_porcelain_error_msgs(void);
/*
* Sets the list of user-friendly error messages to be used by the
* command "cmd" (either merge or checkout)
*/
void set_porcelain_error_msgs(const char **msgs, const char *cmd);

/* merge_trees() but with recursive ancestor consolidation */
int merge_recursive(struct merge_options *o,
Expand Down
2 changes: 1 addition & 1 deletion t/t3030-merge-recursive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ test_expect_success 'fail if the index has unresolved entries' '
grep "You have not concluded your merge" out &&
rm -f .git/MERGE_HEAD &&
test_must_fail git merge "$c5" 2> out &&
grep "Your local changes to .* would be overwritten by merge." out
grep "Your local changes to the following files would be overwritten by merge:" out
'

test_expect_success 'merge-recursive remove conflict' '
Expand Down
3 changes: 2 additions & 1 deletion t/t3400-rebase.sh
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ test_expect_success 'setup: recover' '
test_expect_success 'Show verbose error when HEAD could not be detached' '
>B &&
test_must_fail git rebase topic 2>output.err >output.out &&
grep "Untracked working tree file .B. would be overwritten" output.err
grep "The following untracked working tree files would be overwritten by checkout:" output.err &&
grep B output.err
'
rm -f B

Expand Down
3 changes: 2 additions & 1 deletion t/t3404-rebase-interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ test_expect_success 'abort with error when new base cannot be checked out' '
git rm --cached file1 &&
git commit -m "remove file in base" &&
test_must_fail git rebase -i master > output 2>&1 &&
grep "Untracked working tree file .file1. would be overwritten" \
grep "The following untracked working tree files would be overwritten by checkout:" \
output &&
grep "file1" output &&
! test -d .git/rebase-merge &&
git reset --hard HEAD^
'
Expand Down
125 changes: 125 additions & 0 deletions t/t7609-merge-co-error-msgs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/bin/sh

test_description='unpack-trees error messages'

. ./test-lib.sh


test_expect_success 'setup' '
echo one >one &&
git add one &&
git commit -a -m First &&
git checkout -b branch &&
echo two >two &&
echo three >three &&
echo four >four &&
echo five >five &&
git add two three four five &&
git commit -m Second &&
git checkout master &&
echo other >two &&
echo other >three &&
echo other >four &&
echo other >five
'

cat >expect <<\EOF
error: The following untracked working tree files would be overwritten by merge:
two
three
four
five
Please move or remove them before you can merge.
EOF

test_expect_success 'untracked files overwritten by merge' '
test_must_fail git merge branch 2>out &&
test_cmp out expect
'

cat >expect <<\EOF
error: Your local changes to the following files would be overwritten by merge:
two
three
four
Please, commit your changes or stash them before you can merge.
error: The following untracked working tree files would be overwritten by merge:
five
Please move or remove them before you can merge.
EOF

test_expect_success 'untracked files or local changes ovewritten by merge' '
git add two &&
git add three &&
git add four &&
test_must_fail git merge branch 2>out &&
test_cmp out expect
'

cat >expect <<\EOF
error: Your local changes to the following files would be overwritten by checkout:
rep/two
rep/one
Please, commit your changes or stash them before you can switch branches.
EOF

test_expect_success 'cannot switch branches because of local changes' '
git add five &&
mkdir rep &&
echo one >rep/one &&
echo two >rep/two &&
git add rep/one rep/two &&
git commit -m Fourth &&
git checkout master &&
echo uno >rep/one &&
echo dos >rep/two &&
test_must_fail git checkout branch 2>out &&
test_cmp out expect
'

cat >expect <<\EOF
error: Your local changes to the following files would be overwritten by checkout:
rep/two
rep/one
Please, commit your changes or stash them before you can switch branches.
EOF

test_expect_success 'not uptodate file porcelain checkout error' '
git add rep/one rep/two &&
test_must_fail git checkout branch 2>out &&
test_cmp out expect
'

cat >expect <<\EOF
error: Updating the following directories would lose untracked files in it:
rep2
rep
EOF

test_expect_success 'not_uptodate_dir porcelain checkout error' '
git init uptodate &&
cd uptodate &&
mkdir rep &&
mkdir rep2 &&
touch rep/foo &&
touch rep2/foo &&
git add rep/foo rep2/foo &&
git commit -m init &&
git checkout -b branch &&
git rm rep -r &&
git rm rep2 -r &&
>rep &&
>rep2 &&
git add rep rep2&&
git commit -m "added test as a file" &&
git checkout master &&
>rep/untracked-file &&
>rep2/untracked-file &&
test_must_fail git checkout branch 2>out &&
test_cmp out ../expect
'

test_done
11 changes: 8 additions & 3 deletions tree-walk.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "cache.h"
#include "tree-walk.h"
#include "unpack-trees.h"
#include "tree.h"

static const char *get_mode(const char *str, unsigned int *modep)
Expand Down Expand Up @@ -310,6 +311,7 @@ static void free_extended_entry(struct tree_desc_x *t)
int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
{
int ret = 0;
int error = 0;
struct name_entry *entry = xmalloc(n*sizeof(*entry));
int i;
struct tree_desc_x *tx = xcalloc(n, sizeof(*tx));
Expand Down Expand Up @@ -377,8 +379,11 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
if (!mask)
break;
ret = info->fn(n, mask, dirmask, entry, info);
if (ret < 0)
break;
if (ret < 0) {
error = ret;
if (!info->show_all_errors)
break;
}
mask &= ret;
ret = 0;
for (i = 0; i < n; i++)
Expand All @@ -389,7 +394,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
for (i = 0; i < n; i++)
free_extended_entry(tx + i);
free(tx);
return ret;
return error;
}

static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode)
Expand Down
1 change: 1 addition & 0 deletions tree-walk.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct traverse_info {
unsigned long conflicts;
traverse_callback_t fn;
void *data;
int show_all_errors;
};

int get_tree_entry(const unsigned char *, const char *, unsigned char *, unsigned *);
Expand Down
Loading

0 comments on commit 2eb5469

Please sign in to comment.