Skip to content

Commit

Permalink
do not overwrite files in leading path
Browse files Browse the repository at this point in the history
If the work tree contains an untracked file x, and
unpack-trees wants to checkout a path x/*, the
file x is removed unconditionally.

Instead, apply the same checks that are normally
used for untracked files, and abort if the file
cannot be removed.

Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Clemens Buchacher authored and Junio C Hamano committed Dec 14, 2010
1 parent f7e3bd3 commit b1735b1
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 10 deletions.
2 changes: 1 addition & 1 deletion cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ struct cache_def {

extern int has_symlink_leading_path(const char *name, int len);
extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
extern int has_symlink_or_noent_leading_path(const char *name, int len);
extern int check_leading_path(const char *name, int len);
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
extern void schedule_dir_for_removal(const char *name, int len);
extern void remove_scheduled_dirs(void);
Expand Down
21 changes: 16 additions & 5 deletions symlinks.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,26 @@ int has_symlink_leading_path(const char *name, int len)
}

/*
* Return non-zero if path 'name' has a leading symlink component or
* Return zero if path 'name' has a leading symlink component or
* if some leading path component does not exists.
*
* Return -1 if leading path exists and is a directory.
*
* Return path length if leading path exists and is neither a
* directory nor a symlink.
*/
int has_symlink_or_noent_leading_path(const char *name, int len)
int check_leading_path(const char *name, int len)
{
struct cache_def *cache = &default_cache; /* FIXME */
return lstat_cache(cache, name, len,
FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT) &
(FL_SYMLINK|FL_NOENT);
int flags;
int match_len = lstat_cache_matchlen(cache, name, len, &flags,
FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
if (flags & (FL_SYMLINK|FL_NOENT))
return 0;
else if (flags & FL_DIR)
return -1;
else
return match_len;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion t/t7607-merge-overwrite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ test_expect_success 'will not overwrite untracked subtree' '
test_cmp important sub/f/important
'

test_expect_failure 'will not overwrite untracked file in leading path' '
test_expect_success 'will not overwrite untracked file in leading path' '
git reset --hard c0 &&
rm -rf sub &&
cp important sub &&
Expand Down
16 changes: 13 additions & 3 deletions unpack-trees.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ static void display_error_msgs(struct unpack_trees_options *o)
*/
static void unlink_entry(struct cache_entry *ce)
{
if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
if (!check_leading_path(ce->name, ce_namelen(ce)))
return;
if (remove_or_warn(ce->ce_mode, ce->name))
return;
Expand Down Expand Up @@ -1194,18 +1194,28 @@ static int verify_absent_1(struct cache_entry *ce,
enum unpack_trees_error_types error_type,
struct unpack_trees_options *o)
{
int len;
struct stat st;

if (o->index_only || o->reset || !o->update)
return 0;

if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
len = check_leading_path(ce->name, ce_namelen(ce));
if (!len)
return 0;
else if (len > 0) {
char path[PATH_MAX + 1];
memcpy(path, ce->name, len);
path[len] = 0;
lstat(path, &st);

if (!lstat(ce->name, &st))
return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st,
error_type, o);
} else if (!lstat(ce->name, &st))
return check_ok_to_remove(ce->name, ce_namelen(ce),
ce_to_dtype(ce), ce, &st,
error_type, o);

return 0;
}

Expand Down

0 comments on commit b1735b1

Please sign in to comment.