diff options
-rw-r--r-- | Documentation/git-fast-import.txt | 36 | ||||
-rw-r--r-- | fast-import.c | 13 | ||||
-rwxr-xr-x | t/t9300-fast-import.sh | 51 |
3 files changed, 94 insertions, 6 deletions
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index aeddd5e284..8bb5a0b36b 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -269,7 +269,7 @@ change to the project. data ('from' SP <committish> LF)? ('merge' SP <committish> LF)? - (filemodify | filedelete)* + (filemodify | filedelete | filedeleteall)* LF .... @@ -292,10 +292,12 @@ commit message use a 0 length data. Commit messages are free-form and are not interpreted by Git. Currently they must be encoded in UTF-8, as gfi does not permit other encodings to be specified. -Zero or more `filemodify` and `filedelete` commands may be -included to update the contents of the branch prior to the commit. -These commands can be supplied in any order, gfi is not sensitive -to pathname or operation ordering. +Zero or more `filemodify`, `filedelete` and `filedeleteall` commands +may be included to update the contents of the branch prior to +creating the commit. These commands may be supplied in any order. +However it is recommended that a `filedeleteall` command preceed +all `filemodify` commands in the same commit, as `filedeleteall` +wipes the branch clean (see below). `author` ^^^^^^^^ @@ -459,6 +461,30 @@ first non-empty directory or the root is reached. here `<path>` is the complete path of the file to be removed. See `filemodify` above for a detailed description of `<path>`. +`filedeleteall` +^^^^^^^^^^^^^^^ +Included in a `commit` command to remove all files (and also all +directories) from the branch. This command resets the internal +branch structure to have no files in it, allowing the frontend +to subsequently add all interesting files from scratch. + +.... + 'deleteall' LF +.... + +This command is extremely useful if the frontend does not know +(or does not care to know) what files are currently on the branch, +and therefore cannot generate the proper `filedelete` commands to +update the content. + +Issuing a `filedeleteall` followed by the needed `filemodify` +commands to set the correct content will produce the same results +as sending only the needed `filemodify` and `filedelete` commands. +The `filedeleteall` approach may however require gfi to use slightly +more memory per active branch (less than 1 MiB for even most large +projects); so frontends that can easily obtain only the affected +paths for a commit are encouraged to do so. + `mark` ~~~~~~ Arranges for gfi to save a reference to the current object, allowing diff --git a/fast-import.c b/fast-import.c index c72c5c7a94..f80ddee2fa 100644 --- a/fast-import.c +++ b/fast-import.c @@ -26,7 +26,8 @@ Format of STDIN stream: lf; commit_msg ::= data; - file_change ::= file_del | file_obm | file_inm; + file_change ::= file_clr | file_del | file_obm | file_inm; + file_clr ::= 'deleteall' lf; file_del ::= 'D' sp path_str lf; file_obm ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf; file_inm ::= 'M' sp mode sp 'inline' sp path_str lf @@ -1640,6 +1641,14 @@ static void file_change_d(struct branch *b) free(p_uq); } +static void file_change_deleteall(struct branch *b) +{ + release_tree_content_recursive(b->branch_tree.tree); + hashclr(b->branch_tree.versions[0].sha1); + hashclr(b->branch_tree.versions[1].sha1); + load_tree(&b->branch_tree); +} + static void cmd_from(struct branch *b) { const char *from; @@ -1784,6 +1793,8 @@ static void cmd_new_commit(void) file_change_m(b); else if (!strncmp("D ", command_buf.buf, 2)) file_change_d(b); + else if (!strcmp("deleteall", command_buf.buf)) + file_change_deleteall(b); else die("Unsupported file_change: %s", command_buf.buf); read_next_command(); diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 23a2ba78f6..357a8724dd 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -356,4 +356,55 @@ test_expect_success \ 'test $old_branch != `git-rev-parse --verify branch^0` && test $old_branch = `git-rev-parse --verify branch@{1}`' +### +### series H +### + +test_tick +cat >input <<INPUT_END +commit refs/heads/H +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data <<COMMIT +third +COMMIT + +from refs/heads/branch^0 +M 644 inline i-will-die +data <<EOF +this file will never exist. +EOF + +deleteall +M 644 inline h/e/l/lo +data <<EOF +$file5_data +EOF + +INPUT_END +test_expect_success \ + 'H: deletall, add 1' \ + 'git-fast-import <input && + git-whatchanged H' +test_expect_success \ + 'H: verify pack' \ + 'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done' + +cat >expect <<EOF +:100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file2/newf +:100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D file2/oldf +:100755 000000 85df50785d62d3b05ab03d9cbf7e4a0b49449730 0000000000000000000000000000000000000000 D file4 +:100644 100644 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 fcf778cda181eaa1cbc9e9ce3a2e15ee9f9fe791 R100 newdir/interesting h/e/l/lo +:100755 000000 e74b7d465e52746be2b4bae983670711e6e66657 0000000000000000000000000000000000000000 D newdir/exec.sh +EOF +git-diff-tree -M -r H^ H >actual +test_expect_success \ + 'H: validate old files removed, new files added' \ + 'compare_diff_raw expect actual' + +echo "$file5_data" >expect +test_expect_success \ + 'H: verify file' \ + 'git-cat-file blob H:h/e/l/lo >actual && + diff -u expect actual' + test_done |