Merge branch 'jc/fetch-auto-keep' into next

* jc/fetch-auto-keep:
  Consolidate {receive,fetch}.unpackLimit
  fetch-pack: remove --keep-auto and make it the default.
  Allow fetch-pack to decide keeping the fetched pack without exploding
  Refactor the pack header reading function out of receive-pack.c
  Allow default core.logallrefupdates to be overridden with template's config
  ls-remote and clone: accept --upload-pack=<path> as well.
  rename --exec to --upload-pack for fetch-pack and peek-remote
  Documentation: --amend cannot be combined with -c/-C/-F.
  Documentation/config.txt: Correct info about subsection name
  git-daemon documentation on enabling services.
  reflog inspection: introduce shortcut "-g"
  annotate: use pager
  t/t1300-repo-config.sh: value continued on next line
  git-checkout -m: fix merge case
This commit is contained in:
Junio C Hamano
2007-01-24 18:08:12 -08:00
24 changed files with 262 additions and 99 deletions

View File

@@ -37,8 +37,8 @@ in the section header, like in example below:
--------
Subsection names can contain any characters (doublequote '`"`', backslash
'`\`' and newline have to be entered escaped as '`\"`', '`\\`' and '`\n`',
Subsection names can contain any characters except newline (doublequote
'`"`' and backslash have to be escaped as '`\"`' and '`\\`',
respecitvely) and are case sensitive. Section header cannot span multiple
lines. Variables may belong directly to a section or to a given subsection.
You can have `[section]` if you have `[section "subsection"]`, but you
@@ -295,6 +295,16 @@ diff.renames::
will enable basic rename detection. If set to "copies" or
"copy", it will detect copies, as well.
fetch.unpackLimit::
If the number of objects fetched over the git native
transfer is below this
limit, then the objects will be unpacked into loose object
files. However if the number of received objects equals or
exceeds this limit then the received pack will be stored as
a pack, after adding any missing delta bases. Storing the
pack from a push can make the push operation complete faster,
especially on slow filesystems.
format.headers::
Additional email headers to include in a patch to be submitted
by mail. See gitlink:git-format-patch[1].
@@ -478,3 +488,8 @@ receive.denyNonFastForwards::
even if that push is forced. This configuration variable is
set when initializing a shared repository.
transfer.unpackLimit::
When `fetch.unpackLimit` or `receive.unpackLimit` are
not set, the value of this variable is used instead.

View File

@@ -8,8 +8,8 @@ git-commit - Record changes to the repository
SYNOPSIS
--------
[verse]
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg>]
[--no-verify] [--amend] [-e] [--author <author>]
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg> |
--amend] [--no-verify] [-e] [--author <author>]
[--] [[-i | -o ]<file>...]
DESCRIPTION

View File

@@ -131,14 +131,14 @@ Giving these options is an error when used with `--inetd`; use
the facility of inet daemon to achieve the same before spawning
`git-daemon` if needed.
--enable-service, --disable-service::
--enable=service, --disable=service::
Enable/disable the service site-wide per default. Note
that a service disabled site-wide can still be enabled
per repository if it is marked overridable and the
repository enables the service with an configuration
item.
--allow-override, --forbid-override::
--allow-override=service, --forbid-override=service::
Allow/forbid overriding the site-wide default with per
repository configuration. By default, all the services
are overridable.

View File

@@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository
SYNOPSIS
--------
'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--exec=<git-upload-pack>] [--depth=<n>] [-v] [<host>:]<directory> [<refs>...]
'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [-v] [<host>:]<directory> [<refs>...]
DESCRIPTION
-----------
@@ -45,7 +45,7 @@ OPTIONS
Spend extra cycles to minimize the number of objects to be sent.
Use it on slower connection.
\--exec=<git-upload-pack>::
\--upload-pack=<git-upload-pack>::
Use this to specify the path to 'git-upload-pack' on the
remote side, if is not found on your $PATH.
Installations of sshd ignores the user's environment
@@ -57,6 +57,9 @@ OPTIONS
shells by having a lean .bashrc file (they set most of
the things up in .bash_profile).
\--exec=<git-upload-pack>::
Same as \--upload-pack=<git-upload-pack>.
\--depth=<n>::
Limit fetching to ancestor-chains not longer than n.

View File

@@ -8,7 +8,7 @@ git-peek-remote - List the references in a remote repository
SYNOPSIS
--------
'git-peek-remote' [--exec=<git-upload-pack>] [<host>:]<directory>
'git-peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
DESCRIPTION
-----------
@@ -17,7 +17,7 @@ stores them in the local repository under the same name.
OPTIONS
-------
--exec=<git-upload-pack>::
\--upload-pack=<git-upload-pack>::
Use this to specify the path to 'git-upload-pack' on the
remote side, if it is not found on your $PATH. Some
installations of sshd ignores the user's environment
@@ -29,6 +29,9 @@ OPTIONS
shells, but prefer having a lean .bashrc file (they set most of
the things up in .bash_profile).
\--exec=<git-upload-pack>::
Same \--upload-pack=<git-upload-pack>.
<host>::
A remote host that houses the repository. When this
part is specified, 'git-upload-pack' is invoked via

View File

@@ -192,7 +192,7 @@ limiting may be applied.
In addition to the '<commit>' listed on the command
line, read them from the standard input.
--walk-reflogs::
-g, --walk-reflogs::
Instead of walking the commit ancestry chain, walk
reflog entries from the most recent one to older ones.

View File

@@ -11,7 +11,7 @@ SYNOPSIS
'git-show-branch' [--all] [--remotes] [--topo-order] [--current]
[--more=<n> | --list | --independent | --merge-base]
[--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
'git-show-branch' --reflog[=<n>[,<base>]] [--list] <ref>
'git-show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] <ref>
DESCRIPTION
-----------
@@ -100,8 +100,8 @@ OPTIONS
--reflog[=<n>[,<base>]] <ref>::
Shows <n> most recent ref-log entries for the given
ref. If <base> is given, <n> entries going back from
that entry. <base> can be specified as count or date
that entry. <base> can be specified as count or date.
`-g` can be used as a short-hand for this option.
Note that --more, --list, --independent and --merge-base options
are mutually exclusive.

View File

@@ -257,7 +257,9 @@ static int create_default_files(const char *git_dir, const char *template_path)
}
else {
git_config_set("core.bare", "false");
git_config_set("core.logallrefupdates", "true");
/* allow template config file to override the default */
if (log_all_ref_updates == -1)
git_config_set("core.logallrefupdates", "true");
}
return reinit;
}

View File

@@ -649,11 +649,13 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
dense = 0;
else if (!strcmp(arg, "--date-order"))
lifo = 0;
else if (!strcmp(arg, "--reflog")) {
else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
reflog = DEFAULT_REFLOG;
}
else if (!strncmp(arg, "--reflog=", 9))
parse_reflog_param(arg + 9, &reflog, &reflog_base);
else if (!strncmp(arg, "-g=", 3))
parse_reflog_param(arg + 3, &reflog, &reflog_base);
else
usage(show_branch_usage);
ac--; av++;

View File

@@ -4,16 +4,20 @@
#include "commit.h"
#include "tag.h"
#include "exec_cmd.h"
#include "pack.h"
#include "sideband.h"
static int keep_pack;
static int transfer_unpack_limit = -1;
static int fetch_unpack_limit = -1;
static int unpack_limit = 100;
static int quiet;
static int verbose;
static int fetch_all;
static int depth;
static const char fetch_pack_usage[] =
"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--exec=<git-upload-pack>] [--depth=<n>] [-v] [<host>:]<directory> [<refs>...]";
static const char *exec = "git-upload-pack";
"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [-v] [<host>:]<directory> [<refs>...]";
static const char *uploadpack = "git-upload-pack";
#define COMPLETE (1U << 0)
#define COMMON (1U << 1)
@@ -486,13 +490,58 @@ static pid_t setup_sideband(int fd[2], int xd[2])
return side_pid;
}
static int get_pack(int xd[2], const char **argv)
static int get_pack(int xd[2])
{
int status;
pid_t pid, side_pid;
int fd[2];
const char *argv[20];
char keep_arg[256];
char hdr_arg[256];
const char **av;
int do_keep = keep_pack;
side_pid = setup_sideband(fd, xd);
av = argv;
*hdr_arg = 0;
if (unpack_limit) {
struct pack_header header;
if (read_pack_header(fd[0], &header))
die("protocol error: bad pack header");
snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
ntohl(header.hdr_version), ntohl(header.hdr_entries));
if (ntohl(header.hdr_entries) < unpack_limit)
do_keep = 0;
else
do_keep = 1;
}
if (do_keep) {
*av++ = "index-pack";
*av++ = "--stdin";
if (!quiet)
*av++ = "-v";
if (use_thin_pack)
*av++ = "--fix-thin";
if (keep_pack > 1 || unpack_limit) {
int s = sprintf(keep_arg,
"--keep=fetch-pack %d on ", getpid());
if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
strcpy(keep_arg + s, "localhost");
*av++ = keep_arg;
}
}
else {
*av++ = "unpack-objects";
if (quiet)
*av++ = "-q";
}
if (*hdr_arg)
*av++ = hdr_arg;
*av++ = NULL;
pid = fork();
if (pid < 0)
die("fetch-pack: unable to fork off %s", argv[0]);
@@ -522,39 +571,10 @@ static int get_pack(int xd[2], const char **argv)
die("%s died of unnatural causes %d", argv[0], status);
}
static int explode_rx_pack(int xd[2])
{
const char *argv[3] = { "unpack-objects", quiet ? "-q" : NULL, NULL };
return get_pack(xd, argv);
}
static int keep_rx_pack(int xd[2])
{
const char *argv[6];
char keep_arg[256];
int n = 0;
argv[n++] = "index-pack";
argv[n++] = "--stdin";
if (!quiet)
argv[n++] = "-v";
if (use_thin_pack)
argv[n++] = "--fix-thin";
if (keep_pack > 1) {
int s = sprintf(keep_arg, "--keep=fetch-pack %i on ", getpid());
if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
strcpy(keep_arg + s, "localhost");
argv[n++] = keep_arg;
}
argv[n] = NULL;
return get_pack(xd, argv);
}
static int fetch_pack(int fd[2], int nr_match, char **match)
{
struct ref *ref;
unsigned char sha1[20];
int status;
get_remote_heads(fd[0], &ref, 0, NULL, 0);
if (is_repository_shallow() && !server_supports("shallow"))
@@ -589,8 +609,7 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
*/
fprintf(stderr, "warning: no common commits\n");
status = (keep_pack) ? keep_rx_pack(fd) : explode_rx_pack(fd);
if (status)
if (get_pack(fd))
die("git-fetch-pack: fetch failed.");
all_done:
@@ -625,6 +644,21 @@ static int remove_duplicates(int nr_heads, char **heads)
return dst;
}
static int fetch_pack_config(const char *var, const char *value)
{
if (strcmp(var, "fetch.unpacklimit") == 0) {
fetch_unpack_limit = git_config_int(var, value);
return 0;
}
if (strcmp(var, "transfer.unpacklimit") == 0) {
transfer_unpack_limit = git_config_int(var, value);
return 0;
}
return git_default_config(var, value);
}
static struct lock_file lock;
int main(int argc, char **argv)
@@ -636,6 +670,13 @@ int main(int argc, char **argv)
struct stat st;
setup_git_directory();
setup_ident();
git_config(fetch_pack_config);
if (0 <= transfer_unpack_limit)
unpack_limit = transfer_unpack_limit;
else if (0 <= fetch_unpack_limit)
unpack_limit = fetch_unpack_limit;
nr_heads = 0;
heads = NULL;
@@ -643,8 +684,12 @@ int main(int argc, char **argv)
char *arg = argv[i];
if (*arg == '-') {
if (!strncmp("--upload-pack=", arg, 14)) {
uploadpack = arg + 14;
continue;
}
if (!strncmp("--exec=", arg, 7)) {
exec = arg + 7;
uploadpack = arg + 7;
continue;
}
if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
@@ -653,6 +698,7 @@ int main(int argc, char **argv)
}
if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
keep_pack++;
unpack_limit = 0;
continue;
}
if (!strcmp("--thin", arg)) {
@@ -682,7 +728,7 @@ int main(int argc, char **argv)
}
if (!dest)
usage(fetch_pack_usage);
pid = git_connect(fd, dest, exec);
pid = git_connect(fd, dest, uploadpack);
if (pid < 0)
return 1;
if (heads && nr_heads)

View File

@@ -203,17 +203,12 @@ else
# Match the index to the working tree, and do a three-way.
git diff-files --name-only | git update-index --remove --stdin &&
work=`git write-tree` &&
git read-tree --reset -u $new &&
eval GITHEAD_$new=${new_name:-${branch:-$new}} GITHEAD_$work=local &&
export GITHEAD_$new GITHEAD_$work &&
git merge-recursive $old -- $new $work || exit
git read-tree --reset -u $new || exit
if result=`git write-tree 2>/dev/null`
then
echo >&2 "Trivially automerged."
else
git merge-index -o git-merge-one-file -a
fi
eval GITHEAD_$new=${new_name:-${branch:-$new}} &&
eval GITHEAD_$work=local &&
export GITHEAD_$new GITHEAD_$work &&
git merge-recursive $old -- $new $work
# Do not register the cleanly merged paths in the index yet.
# this is not a real merge before committing, but just carrying

View File

@@ -163,7 +163,9 @@ while
1,-u|1,--upload-pack) usage ;;
*,-u|*,--upload-pack)
shift
upload_pack="--exec=$1" ;;
upload_pack="--upload-pack=$1" ;;
*,--upload-pack=*)
upload_pack=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)') ;;
1,--depth) usage;;
*,--depth)
shift

View File

@@ -3,7 +3,7 @@
# Copyright (c) 2005 Linus Torvalds
# Copyright (c) 2006 Junio C Hamano
USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-u] [--amend] [-e] [--author <author>] [[-i | -o] <path>...]'
USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]'
SUBDIRECTORY_OK=Yes
. git-sh-setup
require_work_tree
@@ -284,9 +284,9 @@ esac
case "$log_given" in
tt*)
die "Only one of -c/-C/-F can be used." ;;
die "Only one of -c/-C/-F/--amend can be used." ;;
*tm*|*mt*)
die "Option -m cannot be combined with -c/-C/-F." ;;
die "Option -m cannot be combined with -c/-C/-F/--amend." ;;
esac
case "$#,$also,$only,$amend" in

View File

@@ -22,7 +22,6 @@ force=
verbose=
update_head_ok=
exec=
upload_pack=
keep=
shallow_depth=
while case "$#" in 0) break ;; esac
@@ -34,8 +33,12 @@ do
--upl|--uplo|--uploa|--upload|--upload-|--upload-p|\
--upload-pa|--upload-pac|--upload-pack)
shift
exec="--exec=$1"
upload_pack="-u $1"
exec="--upload-pack=$1"
;;
--upl=*|--uplo=*|--uploa=*|--upload=*|\
--upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)')
shift
;;
-f|--f|--fo|--for|--forc|--force)
force=t
@@ -94,7 +97,7 @@ then
fi
# Global that is reused later
ls_remote_result=$(git ls-remote $upload_pack "$remote") ||
ls_remote_result=$(git ls-remote $exec "$remote") ||
die "Cannot get the repository state from $remote"
append_fetch_head () {

View File

@@ -23,7 +23,11 @@ do
-u|--u|--up|--upl|--uploa|--upload|--upload-|--upload-p|--upload-pa|\
--upload-pac|--upload-pack)
shift
exec="--exec=$1"
exec="--upload-pack=$1"
shift;;
-u=*|--u=*|--up=*|--upl=*|--uplo=*|--uploa=*|--upload=*|\
--upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)')
shift;;
--)
shift; break ;;

2
git.c
View File

@@ -214,7 +214,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
int option;
} commands[] = {
{ "add", cmd_add, RUN_SETUP | NOT_BARE },
{ "annotate", cmd_annotate, },
{ "annotate", cmd_annotate, USE_PAGER },
{ "apply", cmd_apply },
{ "archive", cmd_archive },
{ "blame", cmd_blame, RUN_SETUP | USE_PAGER },

5
pack.h
View File

@@ -44,4 +44,9 @@ struct pack_header {
#define PACK_IDX_SIGNATURE 0xff744f63 /* "\377tOc" */
extern int verify_pack(struct packed_git *, int);
#define PH_ERROR_EOF (-1)
#define PH_ERROR_PACK_SIGNATURE (-2)
#define PH_ERROR_PROTOCOL (-3)
extern int read_pack_header(int fd, struct pack_header *);
#endif

View File

@@ -3,8 +3,8 @@
#include "pkt-line.h"
static const char peek_remote_usage[] =
"git-peek-remote [--exec=upload-pack] [host:]directory";
static const char *exec = "git-upload-pack";
"git-peek-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
static const char *uploadpack = "git-upload-pack";
static int peek_remote(int fd[2], unsigned flags)
{
@@ -35,8 +35,12 @@ int main(int argc, char **argv)
char *arg = argv[i];
if (*arg == '-') {
if (!strncmp("--upload-pack=", arg, 14)) {
uploadpack = arg + 14;
continue;
}
if (!strncmp("--exec=", arg, 7)) {
exec = arg + 7;
uploadpack = arg + 7;
continue;
}
if (!strcmp("--tags", arg)) {
@@ -60,7 +64,7 @@ int main(int argc, char **argv)
if (!dest || i != argc - 1)
usage(peek_remote_usage);
pid = git_connect(fd, dest, exec);
pid = git_connect(fd, dest, uploadpack);
if (pid < 0)
return 1;
ret = peek_remote(fd, flags);

View File

@@ -10,6 +10,8 @@
static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
static int deny_non_fast_forwards = 0;
static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1;
static int unpack_limit = 100;
static int report_status;
@@ -18,21 +20,22 @@ static int capabilities_sent;
static int receive_pack_config(const char *var, const char *value)
{
git_default_config(var, value);
if (strcmp(var, "receive.denynonfastforwards") == 0)
{
if (strcmp(var, "receive.denynonfastforwards") == 0) {
deny_non_fast_forwards = git_config_bool(var, value);
return 0;
}
if (strcmp(var, "receive.unpacklimit") == 0)
{
unpack_limit = git_config_int(var, value);
if (strcmp(var, "receive.unpacklimit") == 0) {
receive_unpack_limit = git_config_int(var, value);
return 0;
}
return 0;
if (strcmp(var, "transfer.unpacklimit") == 0) {
transfer_unpack_limit = git_config_int(var, value);
return 0;
}
return git_default_config(var, value);
}
static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
@@ -250,20 +253,22 @@ static void read_head_info(void)
static const char *parse_pack_header(struct pack_header *hdr)
{
char *c = (char*)hdr;
ssize_t remaining = sizeof(struct pack_header);
do {
ssize_t r = xread(0, c, remaining);
if (r <= 0)
return "eof before pack header was fully read";
remaining -= r;
c += r;
} while (remaining > 0);
if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
switch (read_pack_header(0, hdr)) {
case PH_ERROR_EOF:
return "eof before pack header was fully read";
case PH_ERROR_PACK_SIGNATURE:
return "protocol error (pack signature mismatch detected)";
if (!pack_version_ok(hdr->hdr_version))
case PH_ERROR_PROTOCOL:
return "protocol error (pack version unsupported)";
return NULL;
default:
return "unknown error in parse_pack_header";
case 0:
return NULL;
}
}
static const char *pack_lockfile;
@@ -429,6 +434,11 @@ int main(int argc, char **argv)
ignore_missing_committer_name();
git_config(receive_pack_config);
if (0 <= transfer_unpack_limit)
unpack_limit = transfer_unpack_limit;
else if (0 <= receive_unpack_limit)
unpack_limit = receive_unpack_limit;
write_head_info();
/* EOF */

View File

@@ -868,7 +868,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
handle_reflog(revs, flags);
continue;
}
if (!strcmp(arg, "--walk-reflogs")) {
if (!strcmp(arg, "-g") ||
!strcmp(arg, "--walk-reflogs")) {
init_reflog_walk(&revs->reflog_info);
continue;
}

View File

@@ -2048,3 +2048,24 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
}
return 0;
}
int read_pack_header(int fd, struct pack_header *header)
{
char *c = (char*)header;
ssize_t remaining = sizeof(struct pack_header);
do {
ssize_t r = xread(fd, c, remaining);
if (r <= 0)
/* "eof before pack header was fully read" */
return PH_ERROR_EOF;
remaining -= r;
c += r;
} while (remaining > 0);
if (header->hdr_signature != htonl(PACK_SIGNATURE))
/* "protocol error (pack signature mismatch detected)" */
return PH_ERROR_PACK_SIGNATURE;
if (!pack_version_ok(header->hdr_version))
/* "protocol error (pack version unsupported)" */
return PH_ERROR_PROTOCOL;
return 0;
}

View File

@@ -424,5 +424,25 @@ newline 123'
test_expect_success 'value with newline' 'git repo-config key.sub value.with\\\
newline'
cat > .git/config <<\EOF
[section]
; comment \
continued = cont\
inued
noncont = not continued ; \
quotecont = "cont;\
inued"
EOF
cat > expect <<\EOF
section.continued=continued
section.noncont=not continued
section.quotecont=cont;inued
EOF
git repo-config --list > result
test_expect_success 'value continued on next line' 'cmp result expect'
test_done

View File

@@ -97,7 +97,8 @@ pull_to_client () {
(
mkdir client &&
cd client &&
git-init 2>> log2.txt
git-init 2>> log2.txt &&
git repo-config transfer.unpacklimit 0
)
add A1

View File

@@ -100,7 +100,33 @@ test_expect_success "checkout -m with dirty tree, renamed" '
git checkout -m renamer &&
fill 1 3 4 5 7 8 >expect &&
diff expect uno &&
! test -f one
! test -f one &&
git diff --cached >current &&
! test -s current
'
test_expect_success 'checkout -m with merge conflict' '
git checkout -f master && git clean &&
fill 1 T 3 4 5 6 S 8 >one &&
if git checkout renamer
then
echo Not happy
false
else
echo "happy - failed correctly"
fi &&
git checkout -m renamer &&
git diff master:one :3:uno |
sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current &&
fill d2 aT d7 aS >expect &&
diff current expect &&
git diff --cached two >current &&
! test -s current
'
test_done