Skip to content

Commit

Permalink
Merge branch 'jc/partial-remove'
Browse files Browse the repository at this point in the history
* jc/partial-remove:
  Document ls-files --with-tree=<tree-ish>
  git-commit: partial commit of paths only removed from the index
  git-commit: Allow partial commit of file removal.
  • Loading branch information
Junio C Hamano committed Sep 15, 2007
2 parents f633616 + a7a0f3d commit 04222b2
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 3 deletions.
9 changes: 8 additions & 1 deletion Documentation/git-ls-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SYNOPSIS
[-x <pattern>|--exclude=<pattern>]
[-X <file>|--exclude-from=<file>]
[--exclude-per-directory=<file>]
[--error-unmatch]
[--error-unmatch] [--with-tree=<tree-ish>]
[--full-name] [--abbrev] [--] [<file>]\*

DESCRIPTION
Expand Down Expand Up @@ -81,6 +81,13 @@ OPTIONS
If any <file> does not appear in the index, treat this as an
error (return 1).

--with-tree=<tree-ish>::
When using --error-unmatch to expand the user supplied
<file> (i.e. path pattern) arguments to paths, pretend
that paths which were removed in the index since the
named <tree-ish> are still present. Using this option
with `-s` or `-u` options does not make any sense.

-t::
Identify the file status with the following tags (followed by
a space) at the start of each line:
Expand Down
78 changes: 78 additions & 0 deletions builtin-ls-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "quote.h"
#include "dir.h"
#include "builtin.h"
#include "tree.h"

static int abbrev;
static int show_deleted;
Expand All @@ -26,6 +27,7 @@ static int prefix_offset;
static const char **pathspec;
static int error_unmatch;
static char *ps_matched;
static const char *with_tree;

static const char *tag_cached = "";
static const char *tag_unmerged = "";
Expand Down Expand Up @@ -247,6 +249,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
continue;
if (show_unmerged && !ce_stage(ce))
continue;
if (ce->ce_flags & htons(CE_UPDATE))
continue;
show_ce_entry(ce_stage(ce) ? tag_unmerged : tag_cached, ce);
}
}
Expand Down Expand Up @@ -332,6 +336,67 @@ static const char *verify_pathspec(const char *prefix)
return real_prefix;
}

/*
* Read the tree specified with --with-tree option
* (typically, HEAD) into stage #1 and then
* squash them down to stage #0. This is used for
* --error-unmatch to list and check the path patterns
* that were given from the command line. We are not
* going to write this index out.
*/
static void overlay_tree(const char *tree_name, const char *prefix)
{
struct tree *tree;
unsigned char sha1[20];
const char **match;
struct cache_entry *last_stage0 = NULL;
int i;

if (get_sha1(tree_name, sha1))
die("tree-ish %s not found.", tree_name);
tree = parse_tree_indirect(sha1);
if (!tree)
die("bad tree-ish %s", tree_name);

/* Hoist the unmerged entries up to stage #3 to make room */
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
if (!ce_stage(ce))
continue;
ce->ce_flags |= htons(CE_STAGEMASK);
}

if (prefix) {
static const char *(matchbuf[2]);
matchbuf[0] = prefix;
matchbuf [1] = NULL;
match = matchbuf;
} else
match = NULL;
if (read_tree(tree, 1, match))
die("unable to read tree entries %s", tree_name);

for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
switch (ce_stage(ce)) {
case 0:
last_stage0 = ce;
/* fallthru */
default:
continue;
case 1:
/*
* If there is stage #0 entry for this, we do not
* need to show it. We use CE_UPDATE bit to mark
* such an entry.
*/
if (last_stage0 &&
!strcmp(last_stage0->name, ce->name))
ce->ce_flags |= htons(CE_UPDATE);
}
}
}

static const char ls_files_usage[] =
"git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
Expand Down Expand Up @@ -452,6 +517,10 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
error_unmatch = 1;
continue;
}
if (!prefixcmp(arg, "--with-tree=")) {
with_tree = arg + 12;
continue;
}
if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
Expand Down Expand Up @@ -503,6 +572,15 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
read_cache();
if (prefix)
prune_cache(prefix);
if (with_tree) {
/*
* Basic sanity check; show-stages and show-unmerged
* would not make any sense with this option.
*/
if (show_stage || show_unmerged)
die("ls-files --with-tree is incompatible with -s or -u");
overlay_tree(with_tree, prefix);
}
show_files(&dir, prefix);

if (ps_matched) {
Expand Down
7 changes: 5 additions & 2 deletions git-commit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,11 @@ t,)
then
refuse_partial "Cannot do a partial commit during a merge."
fi

TMP_INDEX="$GIT_DIR/tmp-index$$"
commit_only=`git ls-files --error-unmatch -- "$@"` || exit
W=
test -z "$initial_commit" && W=--with-tree=HEAD
commit_only=`git ls-files --error-unmatch $W -- "$@"` || exit

# Build a temporary index and update the real index
# the same way.
Expand All @@ -401,7 +404,7 @@ t,)
(
GIT_INDEX_FILE="$NEXT_INDEX"
export GIT_INDEX_FILE
git update-index --remove --stdin
git update-index --add --remove --stdin
) || exit
;;
esac
Expand Down
32 changes: 32 additions & 0 deletions t/t7501-commit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,36 @@ test_expect_success \
'validate git-rev-list output.' \
'diff current expected'

test_expect_success 'partial commit that involves removal (1)' '
git rm --cached file &&
mv file elif &&
git add elif &&
git commit -m "Partial: add elif" elif &&
git diff-tree --name-status HEAD^ HEAD >current &&
echo "A elif" >expected &&
diff expected current
'

test_expect_success 'partial commit that involves removal (2)' '
git commit -m "Partial: remove file" file &&
git diff-tree --name-status HEAD^ HEAD >current &&
echo "D file" >expected &&
diff expected current
'

test_expect_success 'partial commit that involves removal (3)' '
git rm --cached elif &&
echo elif >elif &&
git commit -m "Partial: modify elif" elif &&
git diff-tree --name-status HEAD^ HEAD >current &&
echo "M elif" >expected &&
diff expected current
'

test_done

0 comments on commit 04222b2

Please sign in to comment.