mirror of
https://github.com/git/git.git
synced 2026-03-13 10:23:30 +01:00
Merge commit '96c48153c9a2905fb2f1d588c11e36272635cb79'
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
GIT v1.5.3 Release Notes (draft)
|
||||
GIT v1.5.3 Release Notes
|
||||
========================
|
||||
|
||||
Updates since v1.5.2
|
||||
@@ -10,8 +10,23 @@ Updates since v1.5.2
|
||||
* Thee are a handful pack-objects changes to help you cope better with
|
||||
repositories with pathologically large blobs in them.
|
||||
|
||||
* For people who need to import from Perforce, a front-end for
|
||||
fast-import is in contrib/fast-import/ now.
|
||||
|
||||
* Comes with git-gui 0.8.0.
|
||||
|
||||
* Comes with updated gitk.
|
||||
|
||||
* New commands and options.
|
||||
|
||||
- "git log" learned a new option '--follow', to follow
|
||||
renaming history of a single file.
|
||||
|
||||
- "git-filter-branch" is a reborn cg-admin-rewritehist.
|
||||
|
||||
- "git-cvsserver" learned new options (--base-path, --export-all,
|
||||
--strict-paths) inspired by git-daemon.
|
||||
|
||||
- "git-submodule" command helps you manage the projects from
|
||||
the superproject that contain them.
|
||||
|
||||
@@ -36,9 +51,45 @@ Updates since v1.5.2
|
||||
- "git repack" can be told to split resulting packs to avoid
|
||||
exceeding limit specified with "--max-pack-size".
|
||||
|
||||
- "git fsck" gained --verbose option. This is really really
|
||||
verbose but it might help you identify exact commit that is
|
||||
corrupt in your repository.
|
||||
|
||||
- "git format-patch" learned --numbered-files option. This
|
||||
may be useful for MH users.
|
||||
|
||||
- "git tag -n -l" shows tag annotations while listing tags.
|
||||
|
||||
- "git cvsimport" can optionally use the separate-remote layout.
|
||||
|
||||
- "git blame" can be told to see through commits that changes
|
||||
whitespaces and indentation levels with "-w" option.
|
||||
|
||||
- "git send-email" can be told not to thread the messages when
|
||||
sending out more than one patches.
|
||||
|
||||
- "git config" learned NUL terminated output format via -z to
|
||||
help scripts.
|
||||
|
||||
* Updated behavior of existing commands.
|
||||
|
||||
- "git push" pretends that you immediately fetched back from
|
||||
- "git mergetool" chooses its backend more wisely, taking
|
||||
notice of its environment such as use of X, Gnome/KDE, etc.
|
||||
|
||||
- "gitweb" shows merge commits a lot nicer than before. The
|
||||
default view uses more compact --cc format, while the UI
|
||||
allows to choose normal diff with any parent.
|
||||
|
||||
- snapshot files "gitweb" creates from a repository at
|
||||
$path/$project/.git are more useful. We use $project part
|
||||
in the filename, which we used to discard.
|
||||
|
||||
- "git cvsimort" creates lightweight tag; there is not any
|
||||
interesting information we can record in an annotated tag,
|
||||
and the handcrafted ones the old code created was not
|
||||
properly formed anyway.
|
||||
|
||||
- "git-push" pretends that you immediately fetched back from
|
||||
the remote by updating corresponding remote tracking
|
||||
branches if you have any.
|
||||
|
||||
@@ -48,17 +99,25 @@ Updates since v1.5.2
|
||||
- "git-apply --whitespace=strip" removes blank lines added at
|
||||
the end of the file.
|
||||
|
||||
- fetch over git native protocols with -v shows connection
|
||||
- "git-fetch" over git native protocols with -v shows connection
|
||||
status, and the IP address of the other end, to help
|
||||
diagnosing problems.
|
||||
|
||||
- core.legacyheaders is no more, although we still can read
|
||||
objects created in a new loose object format.
|
||||
- We used to have core.legacyheaders configuration, when
|
||||
set to false, allowed git to write loose objects in a format
|
||||
that mimicks the format used by objects stored in packs. It
|
||||
turns out that this was not so useful. Although we will
|
||||
continue to read objects written in that format, we do not
|
||||
honor that configuration anymore and create loose objects in
|
||||
the legacy/traditional format.
|
||||
|
||||
- "--find-copies-harder" option to diff family can now be
|
||||
spelled as "-C -C" for brevity.
|
||||
|
||||
- "git-mailsplit" (hence "git-am") can read from Maildir
|
||||
formatted mailboxes.
|
||||
|
||||
- "git cvsserver" does not barf upon seeing "cvs login"
|
||||
- "git-cvsserver" does not barf upon seeing "cvs login"
|
||||
request.
|
||||
|
||||
- "pack-objects" honors "delta" attribute set in
|
||||
@@ -68,10 +127,25 @@ Updates since v1.5.2
|
||||
- new-workdir script (in contrib) can now be used with a bare
|
||||
repository.
|
||||
|
||||
- "git-mergetool" learned to use gvimdiff.
|
||||
|
||||
- "gitview" (in contrib) has a better blame interface.
|
||||
|
||||
- "git log" and friends did not handle a commit log message
|
||||
that is larger than 16kB; they do now.
|
||||
|
||||
- "--pretty=oneline" output format for "git log" and friends
|
||||
deals with "malformed" commit log messages that have more
|
||||
than one lines in the first paragraph better. We used to
|
||||
show the first line, cutting the title at mid-sentence; we
|
||||
concatenate them into a single line and treat the result as
|
||||
"oneline".
|
||||
|
||||
* Builds
|
||||
|
||||
-
|
||||
- old-style function definitions (most notably, a function
|
||||
without parameter defined with "func()", not "func(void)")
|
||||
have been eradicated.
|
||||
|
||||
* Performance Tweaks
|
||||
|
||||
@@ -88,6 +162,10 @@ Updates since v1.5.2
|
||||
the object requested the last time, which exploits the
|
||||
locality of references.
|
||||
|
||||
- verifying pack contents done by "git fsck --full" got boost
|
||||
by carefully choosing the order to verify objects in them.
|
||||
|
||||
|
||||
Fixes since v1.5.2
|
||||
------------------
|
||||
|
||||
@@ -96,14 +174,11 @@ this release, unless otherwise noted.
|
||||
|
||||
* Bugfixes
|
||||
|
||||
- .... This has not
|
||||
been backported to 1.5.2.x series, as it is rather an
|
||||
intrusive change.
|
||||
|
||||
- "gitweb" had trouble handling non UTF-8 text with older
|
||||
Encode.pm Perl module.
|
||||
|
||||
--
|
||||
exec >/var/tmp/1
|
||||
O=v1.5.2-45-ged82edc
|
||||
O=v1.5.2-172-g1a8b769
|
||||
O=v1.5.2.2-603-g7c85173
|
||||
echo O=`git describe refs/heads/master`
|
||||
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
|
||||
|
||||
@@ -172,6 +172,13 @@ repository that ends in "/.git" is assumed to be not bare (bare =
|
||||
false), while all other repositories are assumed to be bare (bare
|
||||
= true).
|
||||
|
||||
core.worktree::
|
||||
Set the path to the working tree. The value will not be
|
||||
used in combination with repositories found automatically in
|
||||
a .git directory (i.e. $GIT_DIR is not set).
|
||||
This can be overriden by the GIT_WORK_TREE environment
|
||||
variable and the '--work-tree' command line option.
|
||||
|
||||
core.logAllRefUpdates::
|
||||
Updates to a ref <ref> is logged to the file
|
||||
"$GIT_DIR/logs/<ref>", by appending the new and old
|
||||
|
||||
@@ -9,9 +9,9 @@ git-config - Get and set repository or global options
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-config' [--system | --global] [-z|--null] name [value [value_regex]]
|
||||
'git-config' [--system | --global] --add name value
|
||||
'git-config' [--system | --global] --replace-all name [value [value_regex]]
|
||||
'git-config' [--system | --global] [type] [-z|--null] name [value [value_regex]]
|
||||
'git-config' [--system | --global] [type] --add name value
|
||||
'git-config' [--system | --global] [type] --replace-all name [value [value_regex]]
|
||||
'git-config' [--system | --global] [type] [-z|--null] --get name [value_regex]
|
||||
'git-config' [--system | --global] [type] [-z|--null] --get-all name [value_regex]
|
||||
'git-config' [--system | --global] [type] [-z|--null] --get-regexp name_regex [value_regex]
|
||||
@@ -37,8 +37,7 @@ prepend a single exclamation mark in front (see also <<EXAMPLES>>).
|
||||
The type specifier can be either '--int' or '--bool', which will make
|
||||
'git-config' ensure that the variable(s) are of the given type and
|
||||
convert the value to the canonical form (simple decimal number for int,
|
||||
a "true" or "false" string for bool). Type specifiers currently only
|
||||
take effect for reading operations. If no type specifier is passed,
|
||||
a "true" or "false" string for bool). If no type specifier is passed,
|
||||
no checks or transformations are performed on the value.
|
||||
|
||||
This command will fail if:
|
||||
|
||||
@@ -90,8 +90,15 @@ OPTIONS
|
||||
Show `$GIT_DIR` if defined else show the path to the .git directory.
|
||||
|
||||
--is-inside-git-dir::
|
||||
Return "true" if we are in the git directory, otherwise "false".
|
||||
Some commands require to be run in a working directory.
|
||||
When the current working directory is below the repository
|
||||
directory print "true", otherwise "false".
|
||||
|
||||
--is-inside-work-tree::
|
||||
When the current working directory is inside the work tree of the
|
||||
repository print "true", otherwise "false".
|
||||
|
||||
--is-bare-repository::
|
||||
When the repository is bare print "true", otherwise "false".
|
||||
|
||||
--short, --short=number::
|
||||
Instead of outputting the full SHA1 values of object names try to
|
||||
|
||||
@@ -10,7 +10,8 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate]
|
||||
[--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]
|
||||
[--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]
|
||||
[--help] COMMAND [ARGS]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -103,6 +104,14 @@ OPTIONS
|
||||
Set the path to the repository. This can also be controlled by
|
||||
setting the GIT_DIR environment variable.
|
||||
|
||||
--work-tree=<path>::
|
||||
Set the path to the working tree. The value will not be
|
||||
used in combination with repositories found automatically in
|
||||
a .git directory (i.e. $GIT_DIR is not set).
|
||||
This can also be controlled by setting the GIT_WORK_TREE
|
||||
environment variable and the core.worktree configuration
|
||||
variable.
|
||||
|
||||
--bare::
|
||||
Same as --git-dir=`pwd`.
|
||||
|
||||
@@ -347,6 +356,13 @@ git so take care if using Cogito etc.
|
||||
specifies a path to use instead of the default `.git`
|
||||
for the base of the repository.
|
||||
|
||||
'GIT_WORK_TREE'::
|
||||
Set the path to the working tree. The value will not be
|
||||
used in combination with repositories found automatically in
|
||||
a .git directory (i.e. $GIT_DIR is not set).
|
||||
This can also be controlled by the '--work-tree' command line
|
||||
option and the core.worktree configuration variable.
|
||||
|
||||
git Commits
|
||||
~~~~~~~~~~~
|
||||
'GIT_AUTHOR_NAME'::
|
||||
@@ -396,6 +412,16 @@ other
|
||||
'GIT_PAGER'::
|
||||
This environment variable overrides `$PAGER`.
|
||||
|
||||
'GIT_FLUSH'::
|
||||
If this environment variable is set to "1", then commands such
|
||||
as git-blame (in incremental mode), git-rev-list, git-log,
|
||||
git-whatchanged, etc., will force a flush of the output stream
|
||||
after each commit-oriented record have been flushed. If this
|
||||
variable is set to "0", the output of these commands will be done
|
||||
using completely buffered I/O. If this environment variable is
|
||||
not set, git will choose buffered or record-oriented flushing
|
||||
based on whether stdout appears to be redirected to a file or not.
|
||||
|
||||
'GIT_TRACE'::
|
||||
If this variable is set to "1", "2" or "true" (comparison
|
||||
is case insensitive), git will print `trace:` messages on
|
||||
|
||||
@@ -1459,6 +1459,7 @@ static void found_guilty_entry(struct blame_entry *ent)
|
||||
printf("boundary\n");
|
||||
}
|
||||
write_filename_info(suspect->path);
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -138,9 +138,33 @@ free_strings:
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *normalize_value(const char *key, const char *value)
|
||||
{
|
||||
char *normalized;
|
||||
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (type == T_RAW)
|
||||
normalized = xstrdup(value);
|
||||
else {
|
||||
normalized = xmalloc(64);
|
||||
if (type == T_INT) {
|
||||
int v = git_config_int(key, value);
|
||||
sprintf(normalized, "%d", v);
|
||||
}
|
||||
else if (type == T_BOOL)
|
||||
sprintf(normalized, "%s",
|
||||
git_config_bool(key, value) ? "true" : "false");
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int nongit = 0;
|
||||
char* value;
|
||||
setup_git_directory_gently(&nongit);
|
||||
|
||||
while (1 < argc) {
|
||||
@@ -217,9 +241,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
use_key_regexp = 1;
|
||||
do_all = 1;
|
||||
return get_value(argv[2], NULL);
|
||||
} else
|
||||
|
||||
return git_config_set(argv[1], argv[2]);
|
||||
} else {
|
||||
value = normalize_value(argv[1], argv[2]);
|
||||
return git_config_set(argv[1], value);
|
||||
}
|
||||
case 4:
|
||||
if (!strcmp(argv[1], "--unset"))
|
||||
return git_config_set_multivar(argv[2], NULL, argv[3], 0);
|
||||
@@ -235,17 +260,21 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
use_key_regexp = 1;
|
||||
do_all = 1;
|
||||
return get_value(argv[2], argv[3]);
|
||||
} else if (!strcmp(argv[1], "--add"))
|
||||
return git_config_set_multivar(argv[2], argv[3], "^$", 0);
|
||||
else if (!strcmp(argv[1], "--replace-all"))
|
||||
|
||||
return git_config_set_multivar(argv[2], argv[3], NULL, 1);
|
||||
else
|
||||
|
||||
return git_config_set_multivar(argv[1], argv[2], argv[3], 0);
|
||||
} else if (!strcmp(argv[1], "--add")) {
|
||||
value = normalize_value(argv[2], argv[3]);
|
||||
return git_config_set_multivar(argv[2], value, "^$", 0);
|
||||
} else if (!strcmp(argv[1], "--replace-all")) {
|
||||
value = normalize_value(argv[2], argv[3]);
|
||||
return git_config_set_multivar(argv[2], value, NULL, 1);
|
||||
} else {
|
||||
value = normalize_value(argv[1], argv[2]);
|
||||
return git_config_set_multivar(argv[1], value, argv[3], 0);
|
||||
}
|
||||
case 5:
|
||||
if (!strcmp(argv[1], "--replace-all"))
|
||||
return git_config_set_multivar(argv[2], argv[3], argv[4], 1);
|
||||
if (!strcmp(argv[1], "--replace-all")) {
|
||||
value = normalize_value(argv[2], argv[3]);
|
||||
return git_config_set_multivar(argv[2], value, argv[4], 1);
|
||||
}
|
||||
case 1:
|
||||
default:
|
||||
usage(git_config_set_usage);
|
||||
|
||||
@@ -470,7 +470,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
|
||||
if (require_work_tree &&
|
||||
(is_bare_repository() || is_inside_git_dir()))
|
||||
(!is_inside_work_tree() || is_inside_git_dir()))
|
||||
die("This operation must be run in a work tree");
|
||||
|
||||
pathspec = get_pathspec(prefix, argv + i);
|
||||
|
||||
@@ -100,7 +100,7 @@ static void show_commit(struct commit *commit)
|
||||
printf("%s%c", buf, hdr_termination);
|
||||
free(buf);
|
||||
}
|
||||
fflush(stdout);
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
if (commit->parents) {
|
||||
free_commit_list(commit->parents);
|
||||
commit->parents = NULL;
|
||||
|
||||
@@ -352,6 +352,16 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
||||
: "false");
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--is-inside-work-tree")) {
|
||||
printf("%s\n", is_inside_work_tree() ? "true"
|
||||
: "false");
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--is-bare-repository")) {
|
||||
printf("%s\n", is_bare_repository() ? "true"
|
||||
: "false");
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "--since=")) {
|
||||
show_datestring("--max-age=", arg+8);
|
||||
continue;
|
||||
|
||||
@@ -1,58 +1,79 @@
|
||||
#include "builtin.h"
|
||||
#include "cache.h"
|
||||
|
||||
/*
|
||||
* Remove empty lines from the beginning and end.
|
||||
* Remove trailing spaces from a line.
|
||||
*
|
||||
* Turn multiple consecutive empty lines into just one
|
||||
* empty line. Return true if it is an incomplete line.
|
||||
* If the line ends with newline, it will be removed too.
|
||||
* Returns the new length of the string.
|
||||
*/
|
||||
static int cleanup(char *line)
|
||||
static int cleanup(char *line, int len)
|
||||
{
|
||||
int len = strlen(line);
|
||||
if (len) {
|
||||
if (line[len - 1] == '\n')
|
||||
len--;
|
||||
|
||||
if (len && line[len-1] == '\n') {
|
||||
if (len == 1)
|
||||
return 0;
|
||||
do {
|
||||
unsigned char c = line[len-2];
|
||||
while (len) {
|
||||
unsigned char c = line[len - 1];
|
||||
if (!isspace(c))
|
||||
break;
|
||||
line[len-2] = '\n';
|
||||
len--;
|
||||
line[len] = 0;
|
||||
} while (len > 1);
|
||||
return 0;
|
||||
}
|
||||
line[len] = 0;
|
||||
}
|
||||
return 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void stripspace(FILE *in, FILE *out)
|
||||
/*
|
||||
* Remove empty lines from the beginning and end
|
||||
* and also trailing spaces from every line.
|
||||
*
|
||||
* Turn multiple consecutive empty lines between paragraphs
|
||||
* into just one empty line.
|
||||
*
|
||||
* If the input has only empty lines and spaces,
|
||||
* no output will be produced.
|
||||
*
|
||||
* Enable skip_comments to skip every line starting with "#".
|
||||
*/
|
||||
void stripspace(FILE *in, FILE *out, int skip_comments)
|
||||
{
|
||||
int empties = -1;
|
||||
int incomplete = 0;
|
||||
char line[1024];
|
||||
int alloc = 1024;
|
||||
char *line = xmalloc(alloc);
|
||||
|
||||
while (fgets(line, sizeof(line), in)) {
|
||||
incomplete = cleanup(line);
|
||||
while (fgets(line, alloc, in)) {
|
||||
int len = strlen(line);
|
||||
|
||||
while (len == alloc - 1 && line[len - 1] != '\n') {
|
||||
alloc = alloc_nr(alloc);
|
||||
line = xrealloc(line, alloc);
|
||||
fgets(line + len, alloc - len, in);
|
||||
len += strlen(line + len);
|
||||
}
|
||||
|
||||
if (skip_comments && line[0] == '#')
|
||||
continue;
|
||||
len = cleanup(line, len);
|
||||
|
||||
/* Not just an empty line? */
|
||||
if (line[0] != '\n') {
|
||||
if (len) {
|
||||
if (empties > 0)
|
||||
fputc('\n', out);
|
||||
empties = 0;
|
||||
fputs(line, out);
|
||||
fputc('\n', out);
|
||||
continue;
|
||||
}
|
||||
if (empties < 0)
|
||||
continue;
|
||||
empties++;
|
||||
}
|
||||
if (incomplete)
|
||||
fputc('\n', out);
|
||||
free(line);
|
||||
}
|
||||
|
||||
int cmd_stripspace(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
stripspace(stdin, stdout);
|
||||
stripspace(stdin, stdout, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ extern const char git_version_string[];
|
||||
extern const char git_usage_string[];
|
||||
|
||||
extern void help_unknown_cmd(const char *cmd);
|
||||
extern void stripspace(FILE *in, FILE *out, int skip_comments);
|
||||
extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
|
||||
extern void prune_packed_objects(int);
|
||||
|
||||
|
||||
4
cache.h
4
cache.h
@@ -192,6 +192,7 @@ enum object_type {
|
||||
};
|
||||
|
||||
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
|
||||
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
|
||||
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
|
||||
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
|
||||
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
|
||||
@@ -207,6 +208,7 @@ enum object_type {
|
||||
extern int is_bare_repository_cfg;
|
||||
extern int is_bare_repository(void);
|
||||
extern int is_inside_git_dir(void);
|
||||
extern int is_inside_work_tree(void);
|
||||
extern const char *get_git_dir(void);
|
||||
extern char *get_object_directory(void);
|
||||
extern char *get_refs_directory(void);
|
||||
@@ -534,6 +536,8 @@ extern char git_default_name[MAX_GITNAME];
|
||||
extern const char *git_commit_encoding;
|
||||
extern const char *git_log_output_encoding;
|
||||
|
||||
/* IO helper functions */
|
||||
extern void maybe_flush_or_die(FILE *, const char *);
|
||||
extern int copy_fd(int ifd, int ofd);
|
||||
extern int read_in_full(int fd, void *buf, size_t count);
|
||||
extern int write_in_full(int fd, const void *buf, size_t count);
|
||||
|
||||
@@ -593,6 +593,7 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
|
||||
env_unsetenv(env, ALTERNATE_DB_ENVIRONMENT);
|
||||
env_unsetenv(env, DB_ENVIRONMENT);
|
||||
env_unsetenv(env, GIT_DIR_ENVIRONMENT);
|
||||
env_unsetenv(env, GIT_WORK_TREE_ENVIRONMENT);
|
||||
env_unsetenv(env, GRAFT_ENVIRONMENT);
|
||||
env_unsetenv(env, INDEX_ENVIRONMENT);
|
||||
pid = spawnvpe_pipe("sh", argv, env, pipefd[1], pipefd[0]);
|
||||
|
||||
@@ -312,9 +312,10 @@ case "$GIT_DIR" in
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
export GIT_DIR="$(pwd)/../../$GIT_DIR"
|
||||
GIT_DIR="$(pwd)/../../$GIT_DIR"
|
||||
;;
|
||||
esac
|
||||
export GIT_DIR GIT_WORK_TREE=.
|
||||
|
||||
export GIT_INDEX_FILE="$(pwd)/../index"
|
||||
git-read-tree # seed the index file
|
||||
|
||||
@@ -29,11 +29,7 @@ set_reflog_action() {
|
||||
}
|
||||
|
||||
is_bare_repository () {
|
||||
git-config --bool --get core.bare ||
|
||||
case "$GIT_DIR" in
|
||||
.git | */.git) echo false ;;
|
||||
*) echo true ;;
|
||||
esac
|
||||
git-rev-parse --is-bare-repository
|
||||
}
|
||||
|
||||
cd_to_toplevel () {
|
||||
@@ -48,7 +44,7 @@ cd_to_toplevel () {
|
||||
}
|
||||
|
||||
require_work_tree () {
|
||||
test $(is_bare_repository) = false &&
|
||||
test $(git-rev-parse --is-inside-work-tree) = true &&
|
||||
test $(git-rev-parse --is-inside-git-dir) = false ||
|
||||
die "fatal: $0 cannot be used without a working tree."
|
||||
}
|
||||
|
||||
44
git-svn.perl
44
git-svn.perl
@@ -596,8 +596,7 @@ sub post_fetch_checkout {
|
||||
my $index = $ENV{GIT_INDEX_FILE} || "$ENV{GIT_DIR}/index";
|
||||
return if -f $index;
|
||||
|
||||
chomp(my $bare = `git config --bool --get core.bare`);
|
||||
return if $bare eq 'true';
|
||||
return if command_oneline(qw/rev-parse --is-inside-work-tree/) eq 'false';
|
||||
return if command_oneline(qw/rev-parse --is-inside-git-dir/) eq 'true';
|
||||
command_noisy(qw/read-tree -m -u -v HEAD HEAD/);
|
||||
print STDERR "Checked out HEAD:\n ",
|
||||
@@ -787,12 +786,12 @@ sub read_repo_config {
|
||||
|
||||
sub extract_metadata {
|
||||
my $id = shift or return (undef, undef, undef);
|
||||
my ($url, $rev, $uuid) = ($id =~ /^git-svn-id:\s(\S+?)\@(\d+)
|
||||
my ($url, $rev, $uuid) = ($id =~ /^\s*git-svn-id:\s+(.*)\@(\d+)
|
||||
\s([a-f\d\-]+)$/x);
|
||||
if (!defined $rev || !$uuid || !$url) {
|
||||
# some of the original repositories I made had
|
||||
# identifiers like this:
|
||||
($rev, $uuid) = ($id =~/^git-svn-id:\s(\d+)\@([a-f\d\-]+)/);
|
||||
($rev, $uuid) = ($id =~/^\s*git-svn-id:\s(\d+)\@([a-f\d\-]+)/);
|
||||
}
|
||||
return ($url, $rev, $uuid);
|
||||
}
|
||||
@@ -804,20 +803,29 @@ sub cmt_metadata {
|
||||
|
||||
sub working_head_info {
|
||||
my ($head, $refs) = @_;
|
||||
my ($fh, $ctx) = command_output_pipe('rev-list', $head);
|
||||
while (my $hash = <$fh>) {
|
||||
chomp($hash);
|
||||
my ($url, $rev, $uuid) = cmt_metadata($hash);
|
||||
my ($fh, $ctx) = command_output_pipe('log', $head);
|
||||
my $hash;
|
||||
my %max;
|
||||
while (<$fh>) {
|
||||
if ( m{^commit ($::sha1)$} ) {
|
||||
unshift @$refs, $hash if $hash and $refs;
|
||||
$hash = $1;
|
||||
next;
|
||||
}
|
||||
next unless s{^\s*(git-svn-id:)}{$1};
|
||||
my ($url, $rev, $uuid) = extract_metadata($_);
|
||||
if (defined $url && defined $rev) {
|
||||
next if $max{$url} and $max{$url} < $rev;
|
||||
if (my $gs = Git::SVN->find_by_url($url)) {
|
||||
my $c = $gs->rev_db_get($rev);
|
||||
if ($c && $c eq $hash) {
|
||||
close $fh; # break the pipe
|
||||
return ($url, $rev, $uuid, $gs);
|
||||
} else {
|
||||
$max{$url} ||= $gs->rev_db_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
unshift @$refs, $hash if $refs;
|
||||
}
|
||||
command_close_pipe($fh, $ctx);
|
||||
(undef, undef, undef, undef);
|
||||
@@ -1966,16 +1974,19 @@ sub rebuild {
|
||||
return;
|
||||
}
|
||||
print "Rebuilding $db_path ...\n";
|
||||
my ($rev_list, $ctx) = command_output_pipe("rev-list", $self->refname);
|
||||
my ($log, $ctx) = command_output_pipe("log", $self->refname);
|
||||
my $latest;
|
||||
my $full_url = $self->full_url;
|
||||
remove_username($full_url);
|
||||
my $svn_uuid;
|
||||
while (<$rev_list>) {
|
||||
chomp;
|
||||
my $c = $_;
|
||||
die "Non-SHA1: $c\n" unless $c =~ /^$::sha1$/o;
|
||||
my ($url, $rev, $uuid) = ::cmt_metadata($c);
|
||||
my $c;
|
||||
while (<$log>) {
|
||||
if ( m{^commit ($::sha1)$} ) {
|
||||
$c = $1;
|
||||
next;
|
||||
}
|
||||
next unless s{^\s*(git-svn-id:)}{$1};
|
||||
my ($url, $rev, $uuid) = ::extract_metadata($_);
|
||||
remove_username($url);
|
||||
|
||||
# ignore merges (from set-tree)
|
||||
@@ -1993,7 +2004,7 @@ sub rebuild {
|
||||
$self->rev_db_set($rev, $c);
|
||||
print "r$rev = $c\n";
|
||||
}
|
||||
command_close_pipe($rev_list, $ctx);
|
||||
command_close_pipe($log, $ctx);
|
||||
print "Done rebuilding $db_path\n";
|
||||
}
|
||||
|
||||
@@ -2925,6 +2936,7 @@ sub new {
|
||||
SVN::Client::get_ssl_server_trust_file_provider(),
|
||||
SVN::Client::get_simple_prompt_provider(
|
||||
\&Git::SVN::Prompt::simple, 2),
|
||||
SVN::Client::get_ssl_client_cert_file_provider(),
|
||||
SVN::Client::get_ssl_client_cert_prompt_provider(
|
||||
\&Git::SVN::Prompt::ssl_client_cert, 2),
|
||||
SVN::Client::get_ssl_client_cert_pw_prompt_provider(
|
||||
|
||||
45
git-tag.sh
Normal file → Executable file
45
git-tag.sh
Normal file → Executable file
@@ -19,28 +19,40 @@ do
|
||||
case "$1" in
|
||||
-a)
|
||||
annotate=1
|
||||
shift
|
||||
;;
|
||||
-s)
|
||||
annotate=1
|
||||
signed=1
|
||||
shift
|
||||
;;
|
||||
-f)
|
||||
force=1
|
||||
shift
|
||||
;;
|
||||
-n)
|
||||
case $2 in
|
||||
-*) LINES=1 # no argument
|
||||
case "$#,$2" in
|
||||
1,* | *,-*)
|
||||
LINES=1 # no argument
|
||||
;;
|
||||
*) shift
|
||||
LINES=$(expr "$1" : '\([0-9]*\)')
|
||||
[ -z "$LINES" ] && LINES=1 # 1 line is default when -n is used
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
list=1
|
||||
shift
|
||||
PATTERN="$1" # select tags by shell pattern, not re
|
||||
case $# in
|
||||
0) PATTERN=
|
||||
;;
|
||||
*)
|
||||
PATTERN="$1" # select tags by shell pattern, not re
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
git rev-parse --symbolic --tags | /usr/bin/sort |
|
||||
while read TAG
|
||||
do
|
||||
@@ -51,12 +63,16 @@ do
|
||||
[ "$LINES" -le 0 ] && { echo "$TAG"; continue ;}
|
||||
OBJTYPE=$(git cat-file -t "$TAG")
|
||||
case $OBJTYPE in
|
||||
tag) ANNOTATION=$(git cat-file tag "$TAG" |
|
||||
sed -e '1,/^$/d' \
|
||||
-e '/^-----BEGIN PGP SIGNATURE-----$/Q' )
|
||||
printf "%-15s %s\n" "$TAG" "$ANNOTATION" |
|
||||
sed -e '2,$s/^/ /' \
|
||||
-e "${LINES}q"
|
||||
tag)
|
||||
ANNOTATION=$(git cat-file tag "$TAG" |
|
||||
sed -e '1,/^$/d' |
|
||||
sed -n -e "
|
||||
/^-----BEGIN PGP SIGNATURE-----\$/q
|
||||
2,\$s/^/ /
|
||||
p
|
||||
${LINES}q
|
||||
")
|
||||
printf "%-15s %s\n" "$TAG" "$ANNOTATION"
|
||||
;;
|
||||
*) echo "$TAG"
|
||||
;;
|
||||
@@ -70,7 +86,9 @@ do
|
||||
if test "$#" = "0"; then
|
||||
die "error: option -m needs an argument"
|
||||
else
|
||||
message="$1"
|
||||
message_given=1
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-F)
|
||||
@@ -81,13 +99,19 @@ do
|
||||
else
|
||||
message="$(cat "$1")"
|
||||
message_given=1
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-u)
|
||||
annotate=1
|
||||
signed=1
|
||||
shift
|
||||
username="$1"
|
||||
if test "$#" = "0"; then
|
||||
die "error: option -u needs an argument"
|
||||
else
|
||||
username="$1"
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-d)
|
||||
shift
|
||||
@@ -122,7 +146,6 @@ do
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
[ -n "$list" ] && exit 0
|
||||
|
||||
@@ -37,8 +37,9 @@ esac
|
||||
trap 'rm -f "$GIT_DIR/.tmp-vtag"' 0
|
||||
|
||||
git-cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1
|
||||
|
||||
cat "$GIT_DIR/.tmp-vtag" |
|
||||
sed '/-----BEGIN PGP/Q' |
|
||||
sed -n -e '
|
||||
/^-----BEGIN PGP SIGNATURE-----$/q
|
||||
p
|
||||
' <"$GIT_DIR/.tmp-vtag" |
|
||||
gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1
|
||||
rm -f "$GIT_DIR/.tmp-vtag"
|
||||
|
||||
121
git.c
121
git.c
@@ -4,7 +4,7 @@
|
||||
#include "quote.h"
|
||||
|
||||
const char git_usage_string[] =
|
||||
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate] [--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]";
|
||||
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
|
||||
|
||||
static void prepend_to_path(const char *dir, int len)
|
||||
{
|
||||
@@ -32,7 +32,7 @@ static void prepend_to_path(const char *dir, int len)
|
||||
free(path);
|
||||
}
|
||||
|
||||
static int handle_options(const char*** argv, int* argc)
|
||||
static int handle_options(const char*** argv, int* argc, int* envchanged)
|
||||
{
|
||||
int handled = 0;
|
||||
|
||||
@@ -68,14 +68,34 @@ static int handle_options(const char*** argv, int* argc)
|
||||
usage(git_usage_string);
|
||||
}
|
||||
setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
handled++;
|
||||
} else if (!prefixcmp(cmd, "--git-dir=")) {
|
||||
setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--work-tree")) {
|
||||
if (*argc < 2) {
|
||||
fprintf(stderr, "No directory given for --work-tree.\n" );
|
||||
usage(git_usage_string);
|
||||
}
|
||||
setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
} else if (!prefixcmp(cmd, "--work-tree=")) {
|
||||
setenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--bare")) {
|
||||
static char git_dir[PATH_MAX+1];
|
||||
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown option: %s\n", cmd);
|
||||
usage(git_usage_string);
|
||||
@@ -154,7 +174,7 @@ static int split_cmdline(char *cmdline, const char ***argv)
|
||||
|
||||
static int handle_alias(int *argcp, const char ***argv)
|
||||
{
|
||||
int nongit = 0, ret = 0, saved_errno = errno;
|
||||
int nongit = 0, envchanged = 0, ret = 0, saved_errno = errno;
|
||||
const char *subdir;
|
||||
int count, option_count;
|
||||
const char** new_argv;
|
||||
@@ -175,7 +195,11 @@ static int handle_alias(int *argcp, const char ***argv)
|
||||
alias_string + 1, alias_command);
|
||||
}
|
||||
count = split_cmdline(alias_string, &new_argv);
|
||||
option_count = handle_options(&new_argv, &count);
|
||||
option_count = handle_options(&new_argv, &count, &envchanged);
|
||||
if (envchanged)
|
||||
die("alias '%s' changes environment variables\n"
|
||||
"You can use '!git' in the alias to do this.",
|
||||
alias_command);
|
||||
memmove(new_argv - option_count, new_argv,
|
||||
count * sizeof(char *));
|
||||
new_argv -= option_count;
|
||||
@@ -218,17 +242,56 @@ const char git_version_string[] = GIT_VERSION;
|
||||
* require working tree to be present -- anything uses this needs
|
||||
* RUN_SETUP for reading from the configuration file.
|
||||
*/
|
||||
#define NOT_BARE (1<<2)
|
||||
#define NEED_WORK_TREE (1<<2)
|
||||
|
||||
static void handle_internal_command(int argc, const char **argv, char **envp)
|
||||
struct cmd_struct {
|
||||
const char *cmd;
|
||||
int (*fn)(int, const char **, const char *);
|
||||
int option;
|
||||
};
|
||||
|
||||
static int run_command(struct cmd_struct *p, int argc, const char **argv)
|
||||
{
|
||||
int status;
|
||||
struct stat st;
|
||||
const char *prefix;
|
||||
|
||||
prefix = NULL;
|
||||
if (p->option & RUN_SETUP)
|
||||
prefix = setup_git_directory();
|
||||
if (p->option & USE_PAGER)
|
||||
setup_pager();
|
||||
if ((p->option & NEED_WORK_TREE) &&
|
||||
(!is_inside_work_tree() || is_inside_git_dir()))
|
||||
die("%s must be run in a work tree", p->cmd);
|
||||
trace_argv_printf(argv, argc, "trace: built-in: git");
|
||||
|
||||
status = p->fn(argc, argv, prefix);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Somebody closed stdout? */
|
||||
if (fstat(fileno(stdout), &st))
|
||||
return 0;
|
||||
/* Ignore write errors for pipes and sockets.. */
|
||||
if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
|
||||
return 0;
|
||||
|
||||
/* Check for ENOSPC and EIO errors.. */
|
||||
if (fflush(stdout))
|
||||
die("write failure on standard output: %s", strerror(errno));
|
||||
if (ferror(stdout))
|
||||
die("unknown write failure on standard output");
|
||||
if (fclose(stdout))
|
||||
die("close failed on standard output: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_internal_command(int argc, const char **argv)
|
||||
{
|
||||
const char *cmd = argv[0];
|
||||
static struct cmd_struct {
|
||||
const char *cmd;
|
||||
int (*fn)(int, const char **, const char *);
|
||||
int option;
|
||||
} commands[] = {
|
||||
{ "add", cmd_add, RUN_SETUP | NOT_BARE },
|
||||
static struct cmd_struct commands[] = {
|
||||
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "annotate", cmd_annotate, RUN_SETUP | USE_PAGER },
|
||||
{ "apply", cmd_apply },
|
||||
{ "archive", cmd_archive },
|
||||
@@ -238,9 +301,9 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
||||
{ "cat-file", cmd_cat_file, RUN_SETUP },
|
||||
{ "checkout-index", cmd_checkout_index, RUN_SETUP },
|
||||
{ "check-ref-format", cmd_check_ref_format },
|
||||
{ "check-attr", cmd_check_attr, RUN_SETUP | NOT_BARE },
|
||||
{ "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "cherry", cmd_cherry, RUN_SETUP },
|
||||
{ "cherry-pick", cmd_cherry_pick, RUN_SETUP | NOT_BARE },
|
||||
{ "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
|
||||
{ "config", cmd_config },
|
||||
{ "count-objects", cmd_count_objects, RUN_SETUP },
|
||||
@@ -268,7 +331,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
||||
{ "mailsplit", cmd_mailsplit },
|
||||
{ "merge-base", cmd_merge_base, RUN_SETUP },
|
||||
{ "merge-file", cmd_merge_file },
|
||||
{ "mv", cmd_mv, RUN_SETUP | NOT_BARE },
|
||||
{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "name-rev", cmd_name_rev, RUN_SETUP },
|
||||
{ "pack-objects", cmd_pack_objects, RUN_SETUP },
|
||||
{ "pickaxe", cmd_blame, RUN_SETUP | USE_PAGER },
|
||||
@@ -281,9 +344,9 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
||||
{ "rerere", cmd_rerere, RUN_SETUP },
|
||||
{ "rev-list", cmd_rev_list, RUN_SETUP },
|
||||
{ "rev-parse", cmd_rev_parse, RUN_SETUP },
|
||||
{ "revert", cmd_revert, RUN_SETUP | NOT_BARE },
|
||||
{ "rm", cmd_rm, RUN_SETUP | NOT_BARE },
|
||||
{ "runstatus", cmd_runstatus, RUN_SETUP | NOT_BARE },
|
||||
{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "rm", cmd_rm, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
|
||||
{ "show-branch", cmd_show_branch, RUN_SETUP },
|
||||
{ "show", cmd_show, RUN_SETUP | USE_PAGER },
|
||||
@@ -320,25 +383,13 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(commands); i++) {
|
||||
struct cmd_struct *p = commands+i;
|
||||
const char *prefix;
|
||||
if (strcmp(p->cmd, cmd))
|
||||
continue;
|
||||
|
||||
prefix = NULL;
|
||||
if (p->option & RUN_SETUP)
|
||||
prefix = setup_git_directory();
|
||||
if (p->option & USE_PAGER)
|
||||
setup_pager();
|
||||
if ((p->option & NOT_BARE) &&
|
||||
(is_bare_repository() || is_inside_git_dir()))
|
||||
die("%s must be run in a work tree", cmd);
|
||||
trace_argv_printf(argv, argc, "trace: built-in: git");
|
||||
|
||||
exit(p->fn(argc, argv, prefix));
|
||||
exit(run_command(p, argc, argv));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv, char **envp)
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const char *cmd = argv[0] ? argv[0] : "git-help";
|
||||
char *slash = strrchr(cmd, '/');
|
||||
@@ -381,14 +432,14 @@ int main(int argc, const char **argv, char **envp)
|
||||
if (!prefixcmp(cmd, "git-")) {
|
||||
cmd += 4;
|
||||
argv[0] = cmd;
|
||||
handle_internal_command(argc, argv, envp);
|
||||
handle_internal_command(argc, argv);
|
||||
die("cannot handle %s internally", cmd);
|
||||
}
|
||||
|
||||
/* Look for flags.. */
|
||||
argv++;
|
||||
argc--;
|
||||
handle_options(&argv, &argc);
|
||||
handle_options(&argv, &argc, NULL);
|
||||
if (argc > 0) {
|
||||
if (!prefixcmp(argv[0], "--"))
|
||||
argv[0] += 2;
|
||||
@@ -413,7 +464,7 @@ int main(int argc, const char **argv, char **envp)
|
||||
|
||||
while (1) {
|
||||
/* See if it's an internal command */
|
||||
handle_internal_command(argc, argv, envp);
|
||||
handle_internal_command(argc, argv);
|
||||
|
||||
/* .. then try the external ones */
|
||||
execv_git_cmd(argv);
|
||||
|
||||
@@ -408,5 +408,6 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
|
||||
shown = 1;
|
||||
}
|
||||
opt->loginfo = NULL;
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
return shown;
|
||||
}
|
||||
|
||||
234
setup.c
234
setup.c
@@ -132,7 +132,7 @@ void verify_non_filename(const char *prefix, const char *arg)
|
||||
const char *name;
|
||||
struct stat st;
|
||||
|
||||
if (is_inside_git_dir())
|
||||
if (!is_inside_work_tree() || is_inside_git_dir())
|
||||
return;
|
||||
if (*arg == '-')
|
||||
return; /* flag */
|
||||
@@ -211,42 +211,104 @@ static int inside_git_dir = -1;
|
||||
|
||||
int is_inside_git_dir(void)
|
||||
{
|
||||
if (inside_git_dir < 0) {
|
||||
char buffer[1024];
|
||||
if (inside_git_dir >= 0)
|
||||
return inside_git_dir;
|
||||
die("BUG: is_inside_git_dir called before setup_git_directory");
|
||||
}
|
||||
|
||||
if (is_bare_repository())
|
||||
return (inside_git_dir = 1);
|
||||
if (getcwd(buffer, sizeof(buffer))) {
|
||||
const char *git_dir = get_git_dir(), *cwd = buffer;
|
||||
while (*git_dir && *git_dir == *cwd) {
|
||||
git_dir++;
|
||||
cwd++;
|
||||
}
|
||||
inside_git_dir = !*git_dir;
|
||||
} else
|
||||
inside_git_dir = 0;
|
||||
static int inside_work_tree = -1;
|
||||
|
||||
int is_inside_work_tree(void)
|
||||
{
|
||||
if (inside_git_dir >= 0)
|
||||
return inside_work_tree;
|
||||
die("BUG: is_inside_work_tree called before setup_git_directory");
|
||||
}
|
||||
|
||||
static char *gitworktree_config;
|
||||
|
||||
static int git_setup_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "core.worktree")) {
|
||||
if (gitworktree_config)
|
||||
strlcpy(gitworktree_config, value, PATH_MAX);
|
||||
return 0;
|
||||
}
|
||||
return inside_git_dir;
|
||||
return git_default_config(var, value);
|
||||
}
|
||||
|
||||
const char *setup_git_directory_gently(int *nongit_ok)
|
||||
{
|
||||
static char cwd[PATH_MAX+1];
|
||||
const char *gitdirenv;
|
||||
int len, offset;
|
||||
int minoffset = 0;
|
||||
char worktree[PATH_MAX+1], gitdir[PATH_MAX+1];
|
||||
const char *gitdirenv, *gitworktree;
|
||||
int wt_rel_gitdir = 0;
|
||||
|
||||
/*
|
||||
* If GIT_DIR is set explicitly, we're not going
|
||||
* to do any discovery, but we still do repository
|
||||
* validation.
|
||||
*/
|
||||
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
|
||||
if (gitdirenv) {
|
||||
if (PATH_MAX - 40 < strlen(gitdirenv))
|
||||
die("'$%s' too big", GIT_DIR_ENVIRONMENT);
|
||||
if (is_git_directory(gitdirenv))
|
||||
if (!gitdirenv) {
|
||||
int len, offset;
|
||||
int minoffset = 0;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
if (!getcwd(cwd, sizeof(cwd)-1) || !(cwd[0] == '/' || cwd[1] == ':'))
|
||||
die("Unable to read current working directory");
|
||||
if (cwd[1] == ':')
|
||||
minoffset = 2;
|
||||
#else
|
||||
if (!getcwd(cwd, sizeof(cwd)-1) || cwd[0] != '/')
|
||||
die("Unable to read current working directory");
|
||||
#endif
|
||||
|
||||
offset = len = strlen(cwd);
|
||||
for (;;) {
|
||||
if (is_git_directory(".git"))
|
||||
break;
|
||||
if (offset == 0) {
|
||||
offset = -1;
|
||||
break;
|
||||
}
|
||||
chdir("..");
|
||||
while (offset > minoffset && cwd[--offset] != '/')
|
||||
; /* do nothing */
|
||||
}
|
||||
|
||||
if (offset >= 0) {
|
||||
inside_work_tree = 1;
|
||||
git_config(git_default_config);
|
||||
if (offset == len) {
|
||||
inside_git_dir = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cwd[len++] = '/';
|
||||
cwd[len] = '\0';
|
||||
inside_git_dir = !prefixcmp(cwd + offset + 1, ".git/");
|
||||
return cwd + offset + 1;
|
||||
}
|
||||
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
if (!is_git_directory(".")) {
|
||||
if (nongit_ok) {
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
die("Not a git repository");
|
||||
}
|
||||
setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
|
||||
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
|
||||
if (!gitdirenv)
|
||||
die("getenv after setenv failed");
|
||||
}
|
||||
|
||||
if (PATH_MAX - 40 < strlen(gitdirenv)) {
|
||||
if (nongit_ok) {
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
die("$%s too big", GIT_DIR_ENVIRONMENT);
|
||||
}
|
||||
if (!is_git_directory(gitdirenv)) {
|
||||
if (nongit_ok) {
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
@@ -254,50 +316,94 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||
die("Not a git repository: '%s'", gitdirenv);
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
if (!getcwd(cwd, sizeof(cwd)-1) || !(cwd[0] == '/' || cwd[1] == ':'))
|
||||
die("Unable to read current working directory");
|
||||
if (cwd[1] == ':')
|
||||
minoffset = 2;
|
||||
#else
|
||||
if (!getcwd(cwd, sizeof(cwd)-1) || cwd[0] != '/')
|
||||
die("Unable to read current working directory");
|
||||
#endif
|
||||
if (chdir(gitdirenv)) {
|
||||
if (nongit_ok) {
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
die("Cannot change directory to $%s '%s'",
|
||||
GIT_DIR_ENVIRONMENT, gitdirenv);
|
||||
}
|
||||
if (!getcwd(gitdir, sizeof(gitdir)-1) || gitdir[0] != '/')
|
||||
die("Unable to read current working directory");
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
|
||||
offset = len = strlen(cwd);
|
||||
for (;;) {
|
||||
if (is_git_directory(".git"))
|
||||
break;
|
||||
chdir("..");
|
||||
do {
|
||||
if (offset <= minoffset) {
|
||||
if (is_git_directory(cwd)) {
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
|
||||
inside_git_dir = 1;
|
||||
return NULL;
|
||||
}
|
||||
if (nongit_ok) {
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
die("Not a git repository");
|
||||
/*
|
||||
* In case there is a work tree we may change the directory,
|
||||
* therefore make GIT_DIR an absolute path.
|
||||
*/
|
||||
if (gitdirenv[0] != '/') {
|
||||
setenv(GIT_DIR_ENVIRONMENT, gitdir, 1);
|
||||
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
|
||||
if (!gitdirenv)
|
||||
die("getenv after setenv failed");
|
||||
if (PATH_MAX - 40 < strlen(gitdirenv)) {
|
||||
if (nongit_ok) {
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
} while (offset > minoffset && cwd[--offset] != '/');
|
||||
die("$%s too big after expansion to absolute path",
|
||||
GIT_DIR_ENVIRONMENT);
|
||||
}
|
||||
}
|
||||
|
||||
if (offset == len)
|
||||
return NULL;
|
||||
strcat(cwd, "/");
|
||||
strcat(gitdir, "/");
|
||||
inside_git_dir = !prefixcmp(cwd, gitdir);
|
||||
|
||||
/* Make "offset" point to past the '/', and add a '/' at the end */
|
||||
offset++;
|
||||
cwd[len++] = '/';
|
||||
cwd[len] = 0;
|
||||
inside_git_dir = !prefixcmp(cwd + offset, ".git/");
|
||||
return cwd + offset;
|
||||
gitworktree = getenv(GIT_WORK_TREE_ENVIRONMENT);
|
||||
if (!gitworktree) {
|
||||
gitworktree_config = worktree;
|
||||
worktree[0] = '\0';
|
||||
}
|
||||
git_config(git_setup_config);
|
||||
if (!gitworktree) {
|
||||
gitworktree_config = NULL;
|
||||
if (worktree[0])
|
||||
gitworktree = worktree;
|
||||
if (gitworktree && gitworktree[0] != '/')
|
||||
wt_rel_gitdir = 1;
|
||||
}
|
||||
|
||||
if (wt_rel_gitdir && chdir(gitdirenv))
|
||||
die("Cannot change directory to $%s '%s'",
|
||||
GIT_DIR_ENVIRONMENT, gitdirenv);
|
||||
if (gitworktree && chdir(gitworktree)) {
|
||||
if (nongit_ok) {
|
||||
if (wt_rel_gitdir && chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
if (wt_rel_gitdir)
|
||||
die("Cannot change directory to working tree '%s'"
|
||||
" from $%s", gitworktree, GIT_DIR_ENVIRONMENT);
|
||||
else
|
||||
die("Cannot change directory to working tree '%s'",
|
||||
gitworktree);
|
||||
}
|
||||
if (!getcwd(worktree, sizeof(worktree)-1) || worktree[0] != '/')
|
||||
die("Unable to read current working directory");
|
||||
strcat(worktree, "/");
|
||||
inside_work_tree = !prefixcmp(cwd, worktree);
|
||||
|
||||
if (gitworktree && inside_work_tree && !prefixcmp(worktree, gitdir) &&
|
||||
strcmp(worktree, gitdir)) {
|
||||
inside_git_dir = 0;
|
||||
}
|
||||
|
||||
if (!inside_work_tree) {
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!strcmp(cwd, worktree))
|
||||
return NULL;
|
||||
return cwd+strlen(worktree);
|
||||
}
|
||||
|
||||
int git_config_perm(const char *var, const char *value)
|
||||
|
||||
355
t/t0030-stripspace.sh
Executable file
355
t/t0030-stripspace.sh
Executable file
@@ -0,0 +1,355 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2007 Carlos Rica
|
||||
#
|
||||
|
||||
test_description='git-stripspace'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
t40='A quick brown fox jumps over the lazy do'
|
||||
s40=' '
|
||||
sss="$s40$s40$s40$s40$s40$s40$s40$s40$s40$s40" # 400
|
||||
ttt="$t40$t40$t40$t40$t40$t40$t40$t40$t40$t40" # 400
|
||||
|
||||
test_expect_success \
|
||||
'long lines without spaces should be unchanged' '
|
||||
echo "$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt$ttt$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt$ttt$ttt$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'lines with spaces at the beginning should be unchanged' '
|
||||
echo "$sss$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$sss$sss$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$sss$sss$sss$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'lines with intermediate spaces should be unchanged' '
|
||||
echo "$ttt$sss$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt$sss$sss$ttt" >expect &&
|
||||
git-stripspace <expect >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'consecutive blank lines should be unified' '
|
||||
printf "$ttt\n\n$ttt\n" > expect &&
|
||||
printf "$ttt\n\n\n\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt\n\n$ttt\n" > expect &&
|
||||
printf "$ttt$ttt\n\n\n\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt$ttt\n\n$ttt\n" > expect &&
|
||||
printf "$ttt$ttt$ttt\n\n\n\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n\n$ttt\n" > expect &&
|
||||
printf "$ttt\n\n\n\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n\n$ttt$ttt\n" > expect &&
|
||||
printf "$ttt\n\n\n\n\n$ttt$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n\n$ttt$ttt$ttt\n" > expect &&
|
||||
printf "$ttt\n\n\n\n\n$ttt$ttt$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'consecutive blank lines at the beginning should be removed' '
|
||||
printf "" > expect &&
|
||||
printf "\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "" > expect &&
|
||||
printf "\n\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "" > expect &&
|
||||
printf "$sss\n$sss\n$sss\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "" > expect &&
|
||||
printf "$sss$sss\n$sss\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "" > expect &&
|
||||
printf "\n$sss\n$sss$sss\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "" > expect &&
|
||||
printf "$sss$sss$sss$sss\n\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "" > expect &&
|
||||
printf "\n$sss$sss$sss$sss\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "" > expect &&
|
||||
printf "\n\n$sss$sss$sss$sss\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "\n\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt\n" > expect &&
|
||||
printf "\n\n\n$ttt$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt$ttt\n" > expect &&
|
||||
printf "\n\n\n$ttt$ttt$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt$ttt$ttt\n" > expect &&
|
||||
printf "\n\n\n$ttt$ttt$ttt$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$sss\n$sss\n$sss\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "\n$sss\n$sss$sss\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$sss$sss\n$sss\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$sss$sss$sss\n\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "\n$sss$sss$sss\n\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "\n\n$sss$sss$sss\n$ttt\n" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'consecutive blank lines at the end should be removed' '
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n\n\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt\n" > expect &&
|
||||
printf "$ttt$ttt\n\n\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt$ttt\n" > expect &&
|
||||
printf "$ttt$ttt$ttt\n\n\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt$ttt$ttt\n" > expect &&
|
||||
printf "$ttt$ttt$ttt$ttt\n\n\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n$sss\n$sss\n$sss\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n\n$sss\n$sss$sss\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n$sss$sss\n$sss\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n$sss$sss$sss\n\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n\n$sss$sss$sss\n\n" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" > expect &&
|
||||
printf "$ttt\n\n\n$sss$sss$sss\n" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'text without newline at end should end with newline' '
|
||||
test `printf "$ttt" | git-stripspace | wc -l` -gt 0 &&
|
||||
test `printf "$ttt$ttt" | git-stripspace | wc -l` -gt 0 &&
|
||||
test `printf "$ttt$ttt$ttt" | git-stripspace | wc -l` -gt 0 &&
|
||||
test `printf "$ttt$ttt$ttt$ttt" | git-stripspace | wc -l` -gt 0
|
||||
'
|
||||
|
||||
# text plus spaces at the end:
|
||||
|
||||
test_expect_success \
|
||||
'text plus spaces without newline at end should end with newline' '
|
||||
test `printf "$ttt$sss" | git-stripspace | wc -l` -gt 0 &&
|
||||
test `printf "$ttt$ttt$sss" | git-stripspace | wc -l` -gt 0 &&
|
||||
test `printf "$ttt$ttt$ttt$sss" | git-stripspace | wc -l` -gt 0
|
||||
test `printf "$ttt$sss$sss" | git-stripspace | wc -l` -gt 0 &&
|
||||
test `printf "$ttt$ttt$sss$sss" | git-stripspace | wc -l` -gt 0 &&
|
||||
test `printf "$ttt$sss$sss$sss" | git-stripspace | wc -l` -gt 0
|
||||
'
|
||||
|
||||
test_expect_failure \
|
||||
'text plus spaces without newline at end should not show spaces' '
|
||||
printf "$ttt$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$ttt$ttt$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$ttt$ttt$ttt$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$ttt$sss$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$ttt$ttt$sss$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$ttt$sss$sss$sss" | git-stripspace | grep -q " "
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'text plus spaces without newline should show the correct lines' '
|
||||
printf "$ttt\n" >expect &&
|
||||
printf "$ttt$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" >expect &&
|
||||
printf "$ttt$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt\n" >expect &&
|
||||
printf "$ttt$sss$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt\n" >expect &&
|
||||
printf "$ttt$ttt$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt\n" >expect &&
|
||||
printf "$ttt$ttt$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
printf "$ttt$ttt$ttt\n" >expect &&
|
||||
printf "$ttt$ttt$ttt$sss" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_failure \
|
||||
'text plus spaces at end should not show spaces' '
|
||||
echo "$ttt$sss" | git-stripspace | grep -q " " ||
|
||||
echo "$ttt$ttt$sss" | git-stripspace | grep -q " " ||
|
||||
echo "$ttt$ttt$ttt$sss" | git-stripspace | grep -q " " ||
|
||||
echo "$ttt$sss$sss" | git-stripspace | grep -q " " ||
|
||||
echo "$ttt$ttt$sss$sss" | git-stripspace | grep -q " " ||
|
||||
echo "$ttt$sss$sss$sss" | git-stripspace | grep -q " "
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'text plus spaces at end should be cleaned and newline must remain' '
|
||||
echo "$ttt" >expect &&
|
||||
echo "$ttt$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt" >expect &&
|
||||
echo "$ttt$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt" >expect &&
|
||||
echo "$ttt$sss$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt$ttt" >expect &&
|
||||
echo "$ttt$ttt$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt$ttt" >expect &&
|
||||
echo "$ttt$ttt$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$ttt$ttt$ttt" >expect &&
|
||||
echo "$ttt$ttt$ttt$sss" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
# spaces only:
|
||||
|
||||
test_expect_success \
|
||||
'spaces with newline at end should be replaced with empty string' '
|
||||
printf "" >expect &&
|
||||
|
||||
echo | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$sss$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual &&
|
||||
|
||||
echo "$sss$sss$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_failure \
|
||||
'spaces without newline at end should not show spaces' '
|
||||
printf "" | git-stripspace | grep -q " " ||
|
||||
printf "$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$sss$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$sss$sss$sss" | git-stripspace | grep -q " " ||
|
||||
printf "$sss$sss$sss$sss" | git-stripspace | grep -q " "
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'spaces without newline at end should be replaced with empty string' '
|
||||
printf "" >expect &&
|
||||
|
||||
printf "" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
|
||||
printf "$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
|
||||
printf "$sss$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
|
||||
printf "$sss$sss$sss$sss" | git-stripspace >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
@@ -471,11 +471,57 @@ test_expect_success bool '
|
||||
done &&
|
||||
cmp expect result'
|
||||
|
||||
test_expect_failure 'invalid bool' '
|
||||
test_expect_failure 'invalid bool (--get)' '
|
||||
|
||||
git-config bool.nobool foobar &&
|
||||
git-config --bool --get bool.nobool'
|
||||
|
||||
test_expect_failure 'invalid bool (set)' '
|
||||
|
||||
git-config --bool bool.nobool foobar'
|
||||
|
||||
rm .git/config
|
||||
|
||||
cat > expect <<\EOF
|
||||
[bool]
|
||||
true1 = true
|
||||
true2 = true
|
||||
true3 = true
|
||||
true4 = true
|
||||
false1 = false
|
||||
false2 = false
|
||||
false3 = false
|
||||
false4 = false
|
||||
EOF
|
||||
|
||||
test_expect_success 'set --bool' '
|
||||
|
||||
git-config --bool bool.true1 01 &&
|
||||
git-config --bool bool.true2 -1 &&
|
||||
git-config --bool bool.true3 YeS &&
|
||||
git-config --bool bool.true4 true &&
|
||||
git-config --bool bool.false1 000 &&
|
||||
git-config --bool bool.false2 "" &&
|
||||
git-config --bool bool.false3 nO &&
|
||||
git-config --bool bool.false4 FALSE &&
|
||||
cmp expect .git/config'
|
||||
|
||||
rm .git/config
|
||||
|
||||
cat > expect <<\EOF
|
||||
[int]
|
||||
val1 = 1
|
||||
val2 = -1
|
||||
val3 = 5242880
|
||||
EOF
|
||||
|
||||
test_expect_success 'set --int' '
|
||||
|
||||
git-config --int int.val1 01 &&
|
||||
git-config --int int.val2 -1 &&
|
||||
git-config --int int.val3 5m &&
|
||||
cmp expect .git/config'
|
||||
|
||||
rm .git/config
|
||||
|
||||
git-config quote.leading " test"
|
||||
|
||||
77
t/t1500-rev-parse.sh
Executable file
77
t/t1500-rev-parse.sh
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test git rev-parse'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_rev_parse() {
|
||||
name=$1
|
||||
shift
|
||||
|
||||
test_expect_success "$name: is-bare-repository" \
|
||||
"test '$1' = \"\$(git rev-parse --is-bare-repository)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
|
||||
test_expect_success "$name: is-inside-git-dir" \
|
||||
"test '$1' = \"\$(git rev-parse --is-inside-git-dir)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
|
||||
test_expect_success "$name: is-inside-work-tree" \
|
||||
"test '$1' = \"\$(git rev-parse --is-inside-work-tree)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
|
||||
test_expect_success "$name: prefix" \
|
||||
"test '$1' = \"\$(git rev-parse --show-prefix)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
}
|
||||
|
||||
test_rev_parse toplevel false false true ''
|
||||
|
||||
cd .git || exit 1
|
||||
test_rev_parse .git/ false true true .git/
|
||||
cd objects || exit 1
|
||||
test_rev_parse .git/objects/ false true true .git/objects/
|
||||
cd ../.. || exit 1
|
||||
|
||||
mkdir -p sub/dir || exit 1
|
||||
cd sub/dir || exit 1
|
||||
test_rev_parse subdirectory false false true sub/dir/
|
||||
cd ../.. || exit 1
|
||||
|
||||
git config core.bare true
|
||||
test_rev_parse 'core.bare = true' true false true
|
||||
|
||||
git config --unset core.bare
|
||||
test_rev_parse 'core.bare undefined' false false true
|
||||
|
||||
mkdir work || exit 1
|
||||
cd work || exit 1
|
||||
export GIT_DIR=../.git
|
||||
export GIT_CONFIG="$GIT_DIR"/config
|
||||
|
||||
git config core.bare false
|
||||
test_rev_parse 'GIT_DIR=../.git, core.bare = false' false false true ''
|
||||
|
||||
git config core.bare true
|
||||
test_rev_parse 'GIT_DIR=../.git, core.bare = true' true false true ''
|
||||
|
||||
git config --unset core.bare
|
||||
test_rev_parse 'GIT_DIR=../.git, core.bare undefined' false false true ''
|
||||
|
||||
mv ../.git ../repo.git || exit 1
|
||||
export GIT_DIR=../repo.git
|
||||
export GIT_CONFIG="$GIT_DIR"/config
|
||||
|
||||
git config core.bare false
|
||||
test_rev_parse 'GIT_DIR=../repo.git, core.bare = false' false false true ''
|
||||
|
||||
git config core.bare true
|
||||
test_rev_parse 'GIT_DIR=../repo.git, core.bare = true' true false true ''
|
||||
|
||||
git config --unset core.bare
|
||||
test_rev_parse 'GIT_DIR=../repo.git, core.bare undefined' true false true ''
|
||||
|
||||
test_done
|
||||
92
t/t1501-worktree.sh
Executable file
92
t/t1501-worktree.sh
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test separate work tree'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_rev_parse() {
|
||||
name=$1
|
||||
shift
|
||||
|
||||
test_expect_success "$name: is-bare-repository" \
|
||||
"test '$1' = \"\$(git rev-parse --is-bare-repository)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
|
||||
test_expect_success "$name: is-inside-git-dir" \
|
||||
"test '$1' = \"\$(git rev-parse --is-inside-git-dir)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
|
||||
test_expect_success "$name: is-inside-work-tree" \
|
||||
"test '$1' = \"\$(git rev-parse --is-inside-work-tree)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
|
||||
test_expect_success "$name: prefix" \
|
||||
"test '$1' = \"\$(git rev-parse --show-prefix)\""
|
||||
shift
|
||||
[ $# -eq 0 ] && return
|
||||
}
|
||||
|
||||
mkdir -p work/sub/dir || exit 1
|
||||
mv .git repo.git || exit 1
|
||||
|
||||
say "core.worktree = relative path"
|
||||
export GIT_DIR=repo.git
|
||||
export GIT_CONFIG=$GIT_DIR/config
|
||||
unset GIT_WORK_TREE
|
||||
git config core.worktree ../work
|
||||
test_rev_parse 'outside' false false false
|
||||
cd work || exit 1
|
||||
export GIT_DIR=../repo.git
|
||||
export GIT_CONFIG=$GIT_DIR/config
|
||||
test_rev_parse 'inside' false false true ''
|
||||
cd sub/dir || exit 1
|
||||
export GIT_DIR=../../../repo.git
|
||||
export GIT_CONFIG=$GIT_DIR/config
|
||||
test_rev_parse 'subdirectory' false false true sub/dir/
|
||||
cd ../../.. || exit 1
|
||||
|
||||
say "core.worktree = absolute path"
|
||||
export GIT_DIR=$(pwd)/repo.git
|
||||
export GIT_CONFIG=$GIT_DIR/config
|
||||
git config core.worktree "$(pwd)/work"
|
||||
test_rev_parse 'outside' false false false
|
||||
cd work || exit 1
|
||||
test_rev_parse 'inside' false false true ''
|
||||
cd sub/dir || exit 1
|
||||
test_rev_parse 'subdirectory' false false true sub/dir/
|
||||
cd ../../.. || exit 1
|
||||
|
||||
say "GIT_WORK_TREE=relative path (override core.worktree)"
|
||||
export GIT_DIR=$(pwd)/repo.git
|
||||
export GIT_CONFIG=$GIT_DIR/config
|
||||
git config core.worktree non-existent
|
||||
export GIT_WORK_TREE=work
|
||||
test_rev_parse 'outside' false false false
|
||||
cd work || exit 1
|
||||
export GIT_WORK_TREE=.
|
||||
test_rev_parse 'inside' false false true ''
|
||||
cd sub/dir || exit 1
|
||||
export GIT_WORK_TREE=../..
|
||||
test_rev_parse 'subdirectory' false false true sub/dir/
|
||||
cd ../../.. || exit 1
|
||||
|
||||
mv work repo.git/work
|
||||
|
||||
say "GIT_WORK_TREE=absolute path, work tree below git dir"
|
||||
export GIT_DIR=$(pwd)/repo.git
|
||||
export GIT_CONFIG=$GIT_DIR/config
|
||||
export GIT_WORK_TREE=$(pwd)/repo.git/work
|
||||
test_rev_parse 'outside' false false false
|
||||
cd repo.git || exit 1
|
||||
test_rev_parse 'in repo.git' false true false
|
||||
cd objects || exit 1
|
||||
test_rev_parse 'in repo.git/objects' false true false
|
||||
cd ../work || exit 1
|
||||
test_rev_parse 'in repo.git/work' false false true ''
|
||||
cd sub/dir || exit 1
|
||||
test_rev_parse 'in repo.git/sub/dir' false false true sub/dir/
|
||||
cd ../../../.. || exit 1
|
||||
|
||||
test_done
|
||||
686
t/t7004-tag.sh
Executable file
686
t/t7004-tag.sh
Executable file
@@ -0,0 +1,686 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2007 Carlos Rica
|
||||
#
|
||||
|
||||
test_description='git-tag
|
||||
|
||||
Basic tests for operations with tags.'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
# creating and listing lightweight tags:
|
||||
|
||||
tag_exists () {
|
||||
git show-ref --quiet --verify refs/tags/"$1"
|
||||
}
|
||||
|
||||
# todo: git tag -l now returns always zero, when fixed, change this test
|
||||
test_expect_success 'listing all tags in an empty tree should succeed' \
|
||||
'git tag -l'
|
||||
|
||||
test_expect_success 'listing all tags in an empty tree should output nothing' \
|
||||
'test `git-tag -l | wc -l` -eq 0'
|
||||
|
||||
test_expect_failure 'looking for a tag in an empty tree should fail' \
|
||||
'tag_exists mytag'
|
||||
|
||||
test_expect_success 'creating a tag in an empty tree should fail' '
|
||||
! git-tag mynotag &&
|
||||
! tag_exists mynotag
|
||||
'
|
||||
|
||||
test_expect_success 'creating a tag for HEAD in an empty tree should fail' '
|
||||
! git-tag mytaghead HEAD &&
|
||||
! tag_exists mytaghead
|
||||
'
|
||||
|
||||
test_expect_success 'creating a tag for an unknown revision should fail' '
|
||||
! git-tag mytagnorev aaaaaaaaaaa &&
|
||||
! tag_exists mytagnorev
|
||||
'
|
||||
|
||||
# commit used in the tests, test_tick is also called here to freeze the date:
|
||||
test_expect_success 'creating a tag using default HEAD should succeed' '
|
||||
test_tick &&
|
||||
echo foo >foo &&
|
||||
git add foo &&
|
||||
git commit -m Foo &&
|
||||
git tag mytag
|
||||
'
|
||||
|
||||
test_expect_success 'listing all tags if one exists should succeed' \
|
||||
'git-tag -l'
|
||||
|
||||
test_expect_success 'listing all tags if one exists should output that tag' \
|
||||
'test `git-tag -l` = mytag'
|
||||
|
||||
# pattern matching:
|
||||
|
||||
test_expect_success 'listing a tag using a matching pattern should succeed' \
|
||||
'git-tag -l mytag'
|
||||
|
||||
test_expect_success \
|
||||
'listing a tag using a matching pattern should output that tag' \
|
||||
'test `git-tag -l mytag` = mytag'
|
||||
|
||||
# todo: git tag -l now returns always zero, when fixed, change this test
|
||||
test_expect_success \
|
||||
'listing tags using a non-matching pattern should suceed' \
|
||||
'git-tag -l xxx'
|
||||
|
||||
test_expect_success \
|
||||
'listing tags using a non-matching pattern should output nothing' \
|
||||
'test `git-tag -l xxx | wc -l` -eq 0'
|
||||
|
||||
# special cases for creating tags:
|
||||
|
||||
test_expect_failure \
|
||||
'trying to create a tag with the name of one existing should fail' \
|
||||
'git tag mytag'
|
||||
|
||||
test_expect_success \
|
||||
'trying to create a tag with a non-valid name should fail' '
|
||||
test `git-tag -l | wc -l` -eq 1 &&
|
||||
! git tag "" &&
|
||||
! git tag .othertag &&
|
||||
! git tag "other tag" &&
|
||||
! git tag "othertag^" &&
|
||||
! git tag "other~tag" &&
|
||||
test `git-tag -l | wc -l` -eq 1
|
||||
'
|
||||
|
||||
test_expect_success 'creating a tag using HEAD directly should succeed' '
|
||||
git tag myhead HEAD &&
|
||||
tag_exists myhead
|
||||
'
|
||||
|
||||
# deleting tags:
|
||||
|
||||
test_expect_success 'trying to delete an unknown tag should fail' '
|
||||
! tag_exists unknown-tag &&
|
||||
! git-tag -d unknown-tag
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
myhead
|
||||
mytag
|
||||
EOF
|
||||
test_expect_success \
|
||||
'trying to delete tags without params should succeed and do nothing' '
|
||||
git tag -l > actual && git diff expect actual &&
|
||||
git-tag -d &&
|
||||
git tag -l > actual && git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'deleting two existing tags in one command should succeed' '
|
||||
tag_exists mytag &&
|
||||
tag_exists myhead &&
|
||||
git-tag -d mytag myhead &&
|
||||
! tag_exists mytag &&
|
||||
! tag_exists myhead
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'creating a tag with the name of another deleted one should succeed' '
|
||||
! tag_exists mytag &&
|
||||
git-tag mytag &&
|
||||
tag_exists mytag
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'trying to delete two tags, existing and not, should fail in the 2nd' '
|
||||
tag_exists mytag &&
|
||||
! tag_exists myhead &&
|
||||
! git-tag -d mytag anothertag &&
|
||||
! tag_exists mytag &&
|
||||
! tag_exists myhead
|
||||
'
|
||||
|
||||
test_expect_failure 'trying to delete an already deleted tag should fail' \
|
||||
'git-tag -d mytag'
|
||||
|
||||
# listing various tags with pattern matching:
|
||||
|
||||
cat >expect <<EOF
|
||||
a1
|
||||
aa1
|
||||
cba
|
||||
t210
|
||||
t211
|
||||
v0.2.1
|
||||
v1.0
|
||||
v1.0.1
|
||||
v1.1.3
|
||||
EOF
|
||||
test_expect_success 'listing all tags should print them ordered' '
|
||||
git tag v1.0.1 &&
|
||||
git tag t211 &&
|
||||
git tag aa1 &&
|
||||
git tag v0.2.1 &&
|
||||
git tag v1.1.3 &&
|
||||
git tag cba &&
|
||||
git tag a1 &&
|
||||
git tag v1.0 &&
|
||||
git tag t210 &&
|
||||
git tag -l > actual
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
a1
|
||||
aa1
|
||||
cba
|
||||
EOF
|
||||
test_expect_success \
|
||||
'listing tags with substring as pattern must print those matching' '
|
||||
git-tag -l a > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
v0.2.1
|
||||
v1.0.1
|
||||
v1.1.3
|
||||
EOF
|
||||
test_expect_success \
|
||||
'listing tags with substring as pattern must print those matching' '
|
||||
git-tag -l .1 > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
t210
|
||||
t211
|
||||
EOF
|
||||
test_expect_success \
|
||||
'listing tags with substring as pattern must print those matching' '
|
||||
git-tag -l t21 > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
a1
|
||||
aa1
|
||||
EOF
|
||||
test_expect_success \
|
||||
'listing tags using a name as pattern must print those matching' '
|
||||
git-tag -l a1 > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
v1.0
|
||||
v1.0.1
|
||||
EOF
|
||||
test_expect_success \
|
||||
'listing tags using a name as pattern must print those matching' '
|
||||
git-tag -l v1.0 > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
v1.1.3
|
||||
EOF
|
||||
test_expect_success \
|
||||
'listing tags with ? in the pattern should print those matching' '
|
||||
git-tag -l "1.1?" > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
>expect
|
||||
test_expect_success \
|
||||
'listing tags using v.* should print nothing because none have v.' '
|
||||
git-tag -l "v.*" > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
v0.2.1
|
||||
v1.0
|
||||
v1.0.1
|
||||
v1.1.3
|
||||
EOF
|
||||
test_expect_success \
|
||||
'listing tags using v* should print only those having v' '
|
||||
git-tag -l "v*" > actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
# creating and verifying lightweight tags:
|
||||
|
||||
test_expect_success \
|
||||
'a non-annotated tag created without parameters should point to HEAD' '
|
||||
git-tag non-annotated-tag &&
|
||||
test $(git-cat-file -t non-annotated-tag) = commit &&
|
||||
test $(git-rev-parse non-annotated-tag) = $(git-rev-parse HEAD)
|
||||
'
|
||||
|
||||
test_expect_failure 'trying to verify an unknown tag should fail' \
|
||||
'git-tag -v unknown-tag'
|
||||
|
||||
test_expect_failure \
|
||||
'trying to verify a non-annotated and non-signed tag should fail' \
|
||||
'git-tag -v non-annotated-tag'
|
||||
|
||||
# creating annotated tags:
|
||||
|
||||
get_tag_msg () {
|
||||
git cat-file tag "$1" | sed -e "/BEGIN PGP/q"
|
||||
}
|
||||
|
||||
# run test_tick before committing always gives the time in that timezone
|
||||
get_tag_header () {
|
||||
cat <<EOF
|
||||
object $2
|
||||
type $3
|
||||
tag $1
|
||||
tagger C O Mitter <committer@example.com> $4 -0700
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
commit=$(git rev-parse HEAD)
|
||||
time=$test_tick
|
||||
|
||||
get_tag_header annotated-tag $commit commit $time >expect
|
||||
echo "A message" >>expect
|
||||
test_expect_success \
|
||||
'creating an annotated tag with -m message should succeed' '
|
||||
git-tag -m "A message" annotated-tag &&
|
||||
get_tag_msg annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
cat >msgfile <<EOF
|
||||
Another message
|
||||
in a file.
|
||||
EOF
|
||||
get_tag_header file-annotated-tag $commit commit $time >expect
|
||||
cat msgfile >>expect
|
||||
test_expect_success \
|
||||
'creating an annotated tag with -F messagefile should succeed' '
|
||||
git-tag -F msgfile file-annotated-tag &&
|
||||
get_tag_msg file-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
# blank and empty messages:
|
||||
|
||||
get_tag_header empty-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with an empty -m message should succeed' '
|
||||
git-tag -m "" empty-annotated-tag &&
|
||||
get_tag_msg empty-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
>emptyfile
|
||||
get_tag_header emptyfile-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with an empty -F messagefile should succeed' '
|
||||
git-tag -F emptyfile emptyfile-annotated-tag &&
|
||||
get_tag_msg emptyfile-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
printf '\n\n \n\t\nLeading blank lines\n' >blanksfile
|
||||
printf '\n\t \t \nRepeated blank lines\n' >>blanksfile
|
||||
printf '\n\n\nTrailing spaces \t \n' >>blanksfile
|
||||
printf '\nTrailing blank lines\n\n\t \n\n' >>blanksfile
|
||||
get_tag_header blanks-annotated-tag $commit commit $time >expect
|
||||
cat >>expect <<EOF
|
||||
Leading blank lines
|
||||
|
||||
Repeated blank lines
|
||||
|
||||
Trailing spaces
|
||||
|
||||
Trailing blank lines
|
||||
EOF
|
||||
test_expect_success \
|
||||
'extra blanks in the message for an annotated tag should be removed' '
|
||||
git-tag -F blanksfile blanks-annotated-tag &&
|
||||
get_tag_msg blanks-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
get_tag_header blank-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with blank -m message with spaces should succeed' '
|
||||
git-tag -m " " blank-annotated-tag &&
|
||||
get_tag_msg blank-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
echo ' ' >blankfile
|
||||
echo '' >>blankfile
|
||||
echo ' ' >>blankfile
|
||||
get_tag_header blankfile-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with blank -F messagefile with spaces should succeed' '
|
||||
git-tag -F blankfile blankfile-annotated-tag &&
|
||||
get_tag_msg blankfile-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
printf ' ' >blanknonlfile
|
||||
get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with -F file of spaces and no newline should succeed' '
|
||||
git-tag -F blanknonlfile blanknonlfile-annotated-tag &&
|
||||
get_tag_msg blanknonlfile-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
# messages with commented lines:
|
||||
|
||||
cat >commentsfile <<EOF
|
||||
# A comment
|
||||
|
||||
############
|
||||
The message.
|
||||
############
|
||||
One line.
|
||||
|
||||
|
||||
# commented lines
|
||||
# commented lines
|
||||
|
||||
Another line.
|
||||
# comments
|
||||
|
||||
Last line.
|
||||
EOF
|
||||
get_tag_header comments-annotated-tag $commit commit $time >expect
|
||||
cat >>expect <<EOF
|
||||
The message.
|
||||
One line.
|
||||
|
||||
Another line.
|
||||
|
||||
Last line.
|
||||
EOF
|
||||
test_expect_success \
|
||||
'creating a tag using a -F messagefile with #comments should succeed' '
|
||||
git-tag -F commentsfile comments-annotated-tag &&
|
||||
get_tag_msg comments-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
get_tag_header comment-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with a #comment in the -m message should succeed' '
|
||||
git-tag -m "#comment" comment-annotated-tag &&
|
||||
get_tag_msg comment-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
echo '#comment' >commentfile
|
||||
echo '' >>commentfile
|
||||
echo '####' >>commentfile
|
||||
get_tag_header commentfile-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with #comments in the -F messagefile should succeed' '
|
||||
git-tag -F commentfile commentfile-annotated-tag &&
|
||||
get_tag_msg commentfile-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
printf '#comment' >commentnonlfile
|
||||
get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect
|
||||
test_expect_success \
|
||||
'creating a tag with a file of #comment and no newline should succeed' '
|
||||
git-tag -F commentnonlfile commentnonlfile-annotated-tag &&
|
||||
get_tag_msg commentnonlfile-annotated-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
# trying to verify annotated non-signed tags:
|
||||
|
||||
test_expect_success \
|
||||
'trying to verify an annotated non-signed tag should fail' '
|
||||
tag_exists annotated-tag &&
|
||||
! git-tag -v annotated-tag
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'trying to verify a file-annotated non-signed tag should fail' '
|
||||
tag_exists file-annotated-tag &&
|
||||
! git-tag -v file-annotated-tag
|
||||
'
|
||||
|
||||
# creating and verifying signed tags:
|
||||
|
||||
gpg --version >/dev/null
|
||||
if [ $? -eq 127 ]; then
|
||||
echo "Skipping signed tags tests, because gpg was not found"
|
||||
test_done
|
||||
exit
|
||||
fi
|
||||
|
||||
# key generation info: gpg --homedir t/t7004 --gen-key
|
||||
# Type DSA and Elgamal, size 2048 bits, no expiration date.
|
||||
# Name and email: C O Mitter <committer@example.com>
|
||||
# No password given, to enable non-interactive operation.
|
||||
|
||||
cp -R ../t7004 ./gpghome
|
||||
chmod 0700 gpghome
|
||||
export GNUPGHOME="$(pwd)/gpghome"
|
||||
|
||||
get_tag_header signed-tag $commit commit $time >expect
|
||||
echo 'A signed tag message' >>expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success 'creating a signed tag with -m message should succeed' '
|
||||
git-tag -s -m "A signed tag message" signed-tag &&
|
||||
get_tag_msg signed-tag >actual &&
|
||||
git-diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'verifying a signed tag should succeed' \
|
||||
'git-tag -v signed-tag'
|
||||
|
||||
test_expect_success 'verifying a forged tag should fail' '
|
||||
forged=$(git cat-file tag signed-tag |
|
||||
sed -e "s/signed-tag/forged-tag/" |
|
||||
git mktag) &&
|
||||
git tag forged-tag $forged &&
|
||||
! git-tag -v forged-tag
|
||||
'
|
||||
|
||||
# blank and empty messages for signed tags:
|
||||
|
||||
get_tag_header empty-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with an empty -m message should succeed' '
|
||||
git-tag -s -m "" empty-signed-tag &&
|
||||
get_tag_msg empty-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v empty-signed-tag
|
||||
'
|
||||
|
||||
>sigemptyfile
|
||||
get_tag_header emptyfile-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with an empty -F messagefile should succeed' '
|
||||
git-tag -s -F sigemptyfile emptyfile-signed-tag &&
|
||||
get_tag_msg emptyfile-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v emptyfile-signed-tag
|
||||
'
|
||||
|
||||
printf '\n\n \n\t\nLeading blank lines\n' > sigblanksfile
|
||||
printf '\n\t \t \nRepeated blank lines\n' >>sigblanksfile
|
||||
printf '\n\n\nTrailing spaces \t \n' >>sigblanksfile
|
||||
printf '\nTrailing blank lines\n\n\t \n\n' >>sigblanksfile
|
||||
get_tag_header blanks-signed-tag $commit commit $time >expect
|
||||
cat >>expect <<EOF
|
||||
Leading blank lines
|
||||
|
||||
Repeated blank lines
|
||||
|
||||
Trailing spaces
|
||||
|
||||
Trailing blank lines
|
||||
EOF
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'extra blanks in the message for a signed tag should be removed' '
|
||||
git-tag -s -F sigblanksfile blanks-signed-tag &&
|
||||
get_tag_msg blanks-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v blanks-signed-tag
|
||||
'
|
||||
|
||||
get_tag_header blank-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with a blank -m message should succeed' '
|
||||
git-tag -s -m " " blank-signed-tag &&
|
||||
get_tag_msg blank-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v blank-signed-tag
|
||||
'
|
||||
|
||||
echo ' ' >sigblankfile
|
||||
echo '' >>sigblankfile
|
||||
echo ' ' >>sigblankfile
|
||||
get_tag_header blankfile-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with blank -F file with spaces should succeed' '
|
||||
git-tag -s -F sigblankfile blankfile-signed-tag &&
|
||||
get_tag_msg blankfile-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v blankfile-signed-tag
|
||||
'
|
||||
|
||||
printf ' ' >sigblanknonlfile
|
||||
get_tag_header blanknonlfile-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with spaces and no newline should succeed' '
|
||||
git-tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
|
||||
get_tag_msg blanknonlfile-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v signed-tag
|
||||
'
|
||||
|
||||
# messages with commented lines for signed tags:
|
||||
|
||||
cat >sigcommentsfile <<EOF
|
||||
# A comment
|
||||
|
||||
############
|
||||
The message.
|
||||
############
|
||||
One line.
|
||||
|
||||
|
||||
# commented lines
|
||||
# commented lines
|
||||
|
||||
Another line.
|
||||
# comments
|
||||
|
||||
Last line.
|
||||
EOF
|
||||
get_tag_header comments-signed-tag $commit commit $time >expect
|
||||
cat >>expect <<EOF
|
||||
The message.
|
||||
One line.
|
||||
|
||||
Another line.
|
||||
|
||||
Last line.
|
||||
EOF
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with a -F file with #comments should succeed' '
|
||||
git-tag -s -F sigcommentsfile comments-signed-tag &&
|
||||
get_tag_msg comments-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v comments-signed-tag
|
||||
'
|
||||
|
||||
get_tag_header comment-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with #commented -m message should succeed' '
|
||||
git-tag -s -m "#comment" comment-signed-tag &&
|
||||
get_tag_msg comment-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v comment-signed-tag
|
||||
'
|
||||
|
||||
echo '#comment' >sigcommentfile
|
||||
echo '' >>sigcommentfile
|
||||
echo '####' >>sigcommentfile
|
||||
get_tag_header commentfile-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with #commented -F messagefile should succeed' '
|
||||
git-tag -s -F sigcommentfile commentfile-signed-tag &&
|
||||
get_tag_msg commentfile-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v commentfile-signed-tag
|
||||
'
|
||||
|
||||
printf '#comment' >sigcommentnonlfile
|
||||
get_tag_header commentnonlfile-signed-tag $commit commit $time >expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag with a #comment and no newline should succeed' '
|
||||
git-tag -s -F sigcommentnonlfile commentnonlfile-signed-tag &&
|
||||
get_tag_msg commentnonlfile-signed-tag >actual &&
|
||||
git diff expect actual &&
|
||||
git-tag -v commentnonlfile-signed-tag
|
||||
'
|
||||
|
||||
# tags pointing to objects different from commits:
|
||||
|
||||
tree=$(git rev-parse HEAD^{tree})
|
||||
blob=$(git rev-parse HEAD:foo)
|
||||
tag=$(git rev-parse signed-tag)
|
||||
|
||||
get_tag_header tree-signed-tag $tree tree $time >expect
|
||||
echo "A message for a tree" >>expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag pointing to a tree should succeed' '
|
||||
git-tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} &&
|
||||
get_tag_msg tree-signed-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
get_tag_header blob-signed-tag $blob blob $time >expect
|
||||
echo "A message for a blob" >>expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag pointing to a blob should succeed' '
|
||||
git-tag -s -m "A message for a blob" blob-signed-tag HEAD:foo &&
|
||||
get_tag_msg blob-signed-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
get_tag_header tag-signed-tag $tag tag $time >expect
|
||||
echo "A message for another tag" >>expect
|
||||
echo '-----BEGIN PGP SIGNATURE-----' >>expect
|
||||
test_expect_success \
|
||||
'creating a signed tag pointing to another tag should succeed' '
|
||||
git-tag -s -m "A message for another tag" tag-signed-tag signed-tag &&
|
||||
get_tag_msg tag-signed-tag >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
# try to verify without gpg:
|
||||
|
||||
rm -rf gpghome
|
||||
test_expect_failure \
|
||||
'verify signed tag fails when public key is not present' \
|
||||
'git-tag -v signed-tag'
|
||||
|
||||
test_done
|
||||
BIN
t/t7004/pubring.gpg
Normal file
BIN
t/t7004/pubring.gpg
Normal file
Binary file not shown.
BIN
t/t7004/random_seed
Normal file
BIN
t/t7004/random_seed
Normal file
Binary file not shown.
BIN
t/t7004/secring.gpg
Normal file
BIN
t/t7004/secring.gpg
Normal file
Binary file not shown.
@@ -38,7 +38,7 @@ echo >empty &&
|
||||
git commit -q -m "First Commit" &&
|
||||
git clone -q --local --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
|
||||
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
|
||||
GIT_DIR="$SERVERDIR" git config --bool gitcvs.logfile "$SERVERDIR/gitcvs.log" ||
|
||||
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" ||
|
||||
exit 1
|
||||
|
||||
# note that cvs doesn't accept absolute pathnames
|
||||
@@ -255,7 +255,7 @@ rm -fr "$SERVERDIR"
|
||||
cd "$WORKDIR" &&
|
||||
git clone -q --local --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
|
||||
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
|
||||
GIT_DIR="$SERVERDIR" git config --bool gitcvs.logfile "$SERVERDIR/gitcvs.log" ||
|
||||
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" ||
|
||||
exit 1
|
||||
|
||||
test_expect_success 'cvs update (create new file)' \
|
||||
|
||||
@@ -26,6 +26,7 @@ GIT_COMMITTER_EMAIL=committer@example.com
|
||||
GIT_COMMITTER_NAME='C O Mitter'
|
||||
unset GIT_DIFF_OPTS
|
||||
unset GIT_DIR
|
||||
unset GIT_WORK_TREE
|
||||
unset GIT_EXTERNAL_DIFF
|
||||
unset GIT_INDEX_FILE
|
||||
unset GIT_OBJECT_DIRECTORY
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
#include "cache.h"
|
||||
|
||||
/*
|
||||
* Some cases use stdio, but want to flush after the write
|
||||
* to get error handling (and to get better interactive
|
||||
* behaviour - not buffering excessively).
|
||||
*
|
||||
* Of course, if the flush happened within the write itself,
|
||||
* we've already lost the error code, and cannot report it any
|
||||
* more. So we just ignore that case instead (and hope we get
|
||||
* the right error code on the flush).
|
||||
*
|
||||
* If the file handle is stdout, and stdout is a file, then skip the
|
||||
* flush entirely since it's not needed.
|
||||
*/
|
||||
void maybe_flush_or_die(FILE *f, const char *desc)
|
||||
{
|
||||
static int skip_stdout_flush = -1;
|
||||
struct stat st;
|
||||
char *cp;
|
||||
|
||||
if (f == stdout) {
|
||||
if (skip_stdout_flush < 0) {
|
||||
cp = getenv("GIT_FLUSH");
|
||||
if (cp)
|
||||
skip_stdout_flush = (atoi(cp) == 0);
|
||||
else if ((fstat(fileno(stdout), &st) == 0) &&
|
||||
S_ISREG(st.st_mode))
|
||||
skip_stdout_flush = 1;
|
||||
else
|
||||
skip_stdout_flush = 0;
|
||||
}
|
||||
if (skip_stdout_flush && !ferror(f))
|
||||
return;
|
||||
}
|
||||
if (fflush(f)) {
|
||||
if (errno == EPIPE)
|
||||
exit(0);
|
||||
die("write failure on %s: %s", desc, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int read_in_full(int fd, void *buf, size_t count)
|
||||
{
|
||||
char *p = buf;
|
||||
|
||||
Reference in New Issue
Block a user