Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
53cdd4e1b2 | |||
a77133e383 | |||
6d7c1c8894 | |||
7025616048 | |||
095d65d73b | |||
a94214b75e | |||
c1640aa5d3 | |||
85fd059a89 | |||
3a51e4be9c | |||
ce956fc48e | |||
b344bb1935 | |||
74f3267b0c | |||
cea1e2e94c | |||
ca7ccd5f46 | |||
1bc7a2b38f | |||
b1f809d0ae | |||
712efb1a42 | |||
ca87dd623d | |||
9a6dcb37bd | |||
be33414b18 | |||
92f1c04243 | |||
a45fb697f1 | |||
55292ea25d | |||
e9882c80cd | |||
25d3d32363 | |||
6310071abf | |||
ac00128298 | |||
5ea2c847c5 | |||
eb8c5b872e | |||
721ac4edde | |||
95f95c99f6 | |||
059b37934c | |||
1b77d83cab | |||
9e2326c7e1 | |||
31171d9e45 | |||
a5ccdbe416 | |||
e3e46cdbd4 | |||
d6052abca3 | |||
038e55fec2 |
25
Documentation/RelNotes/1.8.1.2.txt
Normal file
25
Documentation/RelNotes/1.8.1.2.txt
Normal file
@ -0,0 +1,25 @@
|
||||
Git 1.8.1.2 Release Notes
|
||||
=========================
|
||||
|
||||
Fixes since v1.8.1.1
|
||||
--------------------
|
||||
|
||||
* An element on GIT_CEILING_DIRECTORIES list that does not name the
|
||||
real path to a directory (i.e. a symbolic link) could have caused
|
||||
the GIT_DIR discovery logic to escape the ceiling.
|
||||
|
||||
* Command line completion for "tcsh" emitted an unwanted space
|
||||
after completing a single directory name.
|
||||
|
||||
* Command line completion leaked an unnecessary error message while
|
||||
looking for possible matches with paths in <tree-ish>.
|
||||
|
||||
* "git archive" did not record uncompressed size in the header when
|
||||
streaming a zip archive, which confused some implementations of unzip.
|
||||
|
||||
* When users spelled "cc:" in lowercase in the fake "header" in the
|
||||
trailer part, "git send-email" failed to pick up the addresses from
|
||||
there. As e-mail headers field names are case insensitive, this
|
||||
script should follow suit and treat "cc:" and "Cc:" the same way.
|
||||
|
||||
Also contains various documentation fixes.
|
@ -1351,6 +1351,12 @@ help.autocorrect::
|
||||
value is 0 - the command will be just shown but not executed.
|
||||
This is the default.
|
||||
|
||||
help.htmlpath::
|
||||
Specify the path where the HTML documentation resides. File system paths
|
||||
and URLs are supported. HTML pages will be prefixed with this path when
|
||||
help is displayed in the 'web' format. This defaults to the documentation
|
||||
path of your Git installation.
|
||||
|
||||
http.proxy::
|
||||
Override the HTTP proxy, normally configured using the 'http_proxy',
|
||||
'https_proxy', and 'all_proxy' environment variables (see
|
||||
|
@ -72,13 +72,13 @@ if set:
|
||||
GIT_COMMITTER_NAME
|
||||
GIT_COMMITTER_EMAIL
|
||||
GIT_COMMITTER_DATE
|
||||
EMAIL
|
||||
|
||||
(nb "<", ">" and "\n"s are stripped)
|
||||
|
||||
In case (some of) these environment variables are not set, the information
|
||||
is taken from the configuration items user.name and user.email, or, if not
|
||||
present, system user name and the hostname used for outgoing mail (taken
|
||||
present, the environment variable EMAIL, or, if that is not set,
|
||||
system user name and the hostname used for outgoing mail (taken
|
||||
from `/etc/mailname` and falling back to the fully qualified hostname when
|
||||
that file does not exist).
|
||||
|
||||
|
@ -213,11 +213,9 @@ Problems related to tags:
|
||||
* Multiple tags on the same revision are not imported.
|
||||
|
||||
If you suspect that any of these issues may apply to the repository you
|
||||
want to import consider using these alternative tools which proved to be
|
||||
more stable in practice:
|
||||
want to imort, consider using cvs2git:
|
||||
|
||||
* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
|
||||
* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
|
||||
* cvs2git (part of cvs2svn), `http://subversion.apache.org/`
|
||||
|
||||
GIT
|
||||
---
|
||||
|
@ -117,7 +117,7 @@ returns an empty string instead.
|
||||
|
||||
As a special case for the date-type fields, you may specify a format for
|
||||
the date by adding one of `:default`, `:relative`, `:short`, `:local`,
|
||||
`:iso8601` or `:rfc2822` to the end of the fieldname; e.g.
|
||||
`:iso8601`, `:rfc2822` or `:raw` to the end of the fieldname; e.g.
|
||||
`%(taggerdate:relative)`.
|
||||
|
||||
|
||||
|
@ -82,14 +82,6 @@ Functions
|
||||
call free() on the util members of any items that have to be
|
||||
deleted. Preserve the order of the items that are retained.
|
||||
|
||||
`string_list_longest_prefix`::
|
||||
|
||||
Return the longest string within a string_list that is a
|
||||
prefix (in the sense of prefixcmp()) of the specified string,
|
||||
or NULL if no such prefix exists. This function does not
|
||||
require the string_list to be sorted (it does a linear
|
||||
search).
|
||||
|
||||
`print_string_list`::
|
||||
|
||||
Dump a string_list to stdout, useful mainly for debugging purposes. It
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.8.1.1
|
||||
DEF_VER=v1.8.1.2
|
||||
|
||||
LF='
|
||||
'
|
||||
|
2
RelNotes
2
RelNotes
@ -1 +1 @@
|
||||
Documentation/RelNotes/1.8.1.1.txt
|
||||
Documentation/RelNotes/1.8.1.2.txt
|
105
abspath.c
105
abspath.c
@ -15,16 +15,34 @@ int is_directory(const char *path)
|
||||
#define MAXDEPTH 5
|
||||
|
||||
/*
|
||||
* Use this to get the real path, i.e. resolve links. If you want an
|
||||
* absolute path but don't mind links, use absolute_path.
|
||||
* Return the real path (i.e., absolute path, with symlinks resolved
|
||||
* and extra slashes removed) equivalent to the specified path. (If
|
||||
* you want an absolute path but don't mind links, use
|
||||
* absolute_path().) The return value is a pointer to a static
|
||||
* buffer.
|
||||
*
|
||||
* The input and all intermediate paths must be shorter than MAX_PATH.
|
||||
* The directory part of path (i.e., everything up to the last
|
||||
* dir_sep) must denote a valid, existing directory, but the last
|
||||
* component need not exist. If die_on_error is set, then die with an
|
||||
* informative error message if there is a problem. Otherwise, return
|
||||
* NULL on errors (without generating any output).
|
||||
*
|
||||
* If path is our buffer, then return path, as it's already what the
|
||||
* user wants.
|
||||
*/
|
||||
const char *real_path(const char *path)
|
||||
static const char *real_path_internal(const char *path, int die_on_error)
|
||||
{
|
||||
static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
|
||||
char *retval = NULL;
|
||||
|
||||
/*
|
||||
* If we have to temporarily chdir(), store the original CWD
|
||||
* here so that we can chdir() back to it at the end of the
|
||||
* function:
|
||||
*/
|
||||
char cwd[1024] = "";
|
||||
|
||||
int buf_index = 1;
|
||||
|
||||
int depth = MAXDEPTH;
|
||||
@ -35,11 +53,19 @@ const char *real_path(const char *path)
|
||||
if (path == buf || path == next_buf)
|
||||
return path;
|
||||
|
||||
if (!*path)
|
||||
die("The empty string is not a valid path");
|
||||
if (!*path) {
|
||||
if (die_on_error)
|
||||
die("The empty string is not a valid path");
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
|
||||
die ("Too long path: %.*s", 60, path);
|
||||
if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
|
||||
if (die_on_error)
|
||||
die("Too long path: %.*s", 60, path);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
while (depth--) {
|
||||
if (!is_directory(buf)) {
|
||||
@ -54,20 +80,36 @@ const char *real_path(const char *path)
|
||||
}
|
||||
|
||||
if (*buf) {
|
||||
if (!*cwd && !getcwd(cwd, sizeof(cwd)))
|
||||
die_errno ("Could not get current working directory");
|
||||
if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
|
||||
if (die_on_error)
|
||||
die_errno("Could not get current working directory");
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (chdir(buf))
|
||||
die_errno ("Could not switch to '%s'", buf);
|
||||
if (chdir(buf)) {
|
||||
if (die_on_error)
|
||||
die_errno("Could not switch to '%s'", buf);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
if (!getcwd(buf, PATH_MAX)) {
|
||||
if (die_on_error)
|
||||
die_errno("Could not get current working directory");
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
if (!getcwd(buf, PATH_MAX))
|
||||
die_errno ("Could not get current working directory");
|
||||
|
||||
if (last_elem) {
|
||||
size_t len = strlen(buf);
|
||||
if (len + strlen(last_elem) + 2 > PATH_MAX)
|
||||
die ("Too long path name: '%s/%s'",
|
||||
buf, last_elem);
|
||||
if (len + strlen(last_elem) + 2 > PATH_MAX) {
|
||||
if (die_on_error)
|
||||
die("Too long path name: '%s/%s'",
|
||||
buf, last_elem);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
if (len && !is_dir_sep(buf[len-1]))
|
||||
buf[len++] = '/';
|
||||
strcpy(buf + len, last_elem);
|
||||
@ -77,10 +119,18 @@ const char *real_path(const char *path)
|
||||
|
||||
if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
|
||||
ssize_t len = readlink(buf, next_buf, PATH_MAX);
|
||||
if (len < 0)
|
||||
die_errno ("Invalid symlink '%s'", buf);
|
||||
if (PATH_MAX <= len)
|
||||
die("symbolic link too long: %s", buf);
|
||||
if (len < 0) {
|
||||
if (die_on_error)
|
||||
die_errno("Invalid symlink '%s'", buf);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
if (PATH_MAX <= len) {
|
||||
if (die_on_error)
|
||||
die("symbolic link too long: %s", buf);
|
||||
else
|
||||
goto error_out;
|
||||
}
|
||||
next_buf[len] = '\0';
|
||||
buf = next_buf;
|
||||
buf_index = 1 - buf_index;
|
||||
@ -89,10 +139,23 @@ const char *real_path(const char *path)
|
||||
break;
|
||||
}
|
||||
|
||||
retval = buf;
|
||||
error_out:
|
||||
free(last_elem);
|
||||
if (*cwd && chdir(cwd))
|
||||
die_errno ("Could not change back to '%s'", cwd);
|
||||
|
||||
return buf;
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char *real_path(const char *path)
|
||||
{
|
||||
return real_path_internal(path, 1);
|
||||
}
|
||||
|
||||
const char *real_path_if_valid(const char *path)
|
||||
{
|
||||
return real_path_internal(path, 0);
|
||||
}
|
||||
|
||||
static const char *get_pwd_cwd(void)
|
||||
|
@ -240,7 +240,7 @@ static int write_zip_entry(struct archiver_args *args,
|
||||
(mode & 0111) ? ((mode) << 16) : 0;
|
||||
if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
|
||||
method = 8;
|
||||
compressed_size = size;
|
||||
compressed_size = (method == 0) ? size : 0;
|
||||
|
||||
if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
|
||||
size > big_file_threshold) {
|
||||
@ -313,10 +313,7 @@ static int write_zip_entry(struct archiver_args *args,
|
||||
copy_le16(header.compression_method, method);
|
||||
copy_le16(header.mtime, zip_time);
|
||||
copy_le16(header.mdate, zip_date);
|
||||
if (flags & ZIP_STREAM)
|
||||
set_zip_header_data_desc(&header, 0, 0, 0);
|
||||
else
|
||||
set_zip_header_data_desc(&header, size, compressed_size, crc);
|
||||
set_zip_header_data_desc(&header, size, compressed_size, crc);
|
||||
copy_le16(header.filename_length, pathlen);
|
||||
copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE);
|
||||
write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
|
||||
|
2
attr.c
2
attr.c
@ -704,7 +704,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
|
||||
|
||||
if (*n == ATTR__UNKNOWN) {
|
||||
debug_set(what,
|
||||
a->is_macro ? a->u.attr->name : a->u.pattern,
|
||||
a->is_macro ? a->u.attr->name : a->u.pat.pattern,
|
||||
attr, v);
|
||||
*n = v;
|
||||
rem--;
|
||||
|
3
cache.h
3
cache.h
@ -714,10 +714,11 @@ static inline int is_absolute_path(const char *path)
|
||||
}
|
||||
int is_directory(const char *);
|
||||
const char *real_path(const char *path);
|
||||
const char *real_path_if_valid(const char *path);
|
||||
const char *absolute_path(const char *path);
|
||||
const char *relative_path(const char *abs, const char *base);
|
||||
int normalize_path_copy(char *dst, const char *src);
|
||||
int longest_ancestor_length(const char *path, const char *prefix_list);
|
||||
int longest_ancestor_length(const char *path, struct string_list *prefixes);
|
||||
char *strip_path_suffix(const char *path, const char *suffix);
|
||||
int daemon_avoid_alias(const char *path);
|
||||
int offset_1st_component(const char *path);
|
||||
|
@ -397,7 +397,7 @@ __git_complete_revlist_file ()
|
||||
*) pfx="$ref:$pfx" ;;
|
||||
esac
|
||||
|
||||
__gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \
|
||||
__gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \
|
||||
| sed '/^100... blob /{
|
||||
s,^.* ,,
|
||||
s,$, ,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#
|
||||
# To use this completion script:
|
||||
#
|
||||
# 0) You need tcsh 6.16.00 or newer.
|
||||
# 1) Copy both this file and the bash completion script to ${HOME}.
|
||||
# You _must_ use the name ${HOME}/.git-completion.bash for the
|
||||
# bash script.
|
||||
@ -24,6 +25,15 @@
|
||||
# set autolist=ambiguous
|
||||
# It will tell tcsh to list the possible completion choices.
|
||||
|
||||
set __git_tcsh_completion_version = `\echo ${tcsh} | \sed 's/\./ /g'`
|
||||
if ( ${__git_tcsh_completion_version[1]} < 6 || \
|
||||
( ${__git_tcsh_completion_version[1]} == 6 && \
|
||||
${__git_tcsh_completion_version[2]} < 16 ) ) then
|
||||
echo "git-completion.tcsh: Your version of tcsh is too old, you need version 6.16.00 or newer. Git completion will not work."
|
||||
exit
|
||||
endif
|
||||
unset __git_tcsh_completion_version
|
||||
|
||||
set __git_tcsh_completion_original_script = ${HOME}/.git-completion.bash
|
||||
set __git_tcsh_completion_script = ${HOME}/.git-completion.tcsh.bash
|
||||
|
||||
@ -64,9 +74,7 @@ fi
|
||||
_\${1}
|
||||
|
||||
IFS=\$'\n'
|
||||
if [ \${#COMPREPLY[*]} -gt 0 ]; then
|
||||
echo "\${COMPREPLY[*]}" | sort | uniq
|
||||
else
|
||||
if [ \${#COMPREPLY[*]} -eq 0 ]; then
|
||||
# No completions suggested. In this case, we want tcsh to perform
|
||||
# standard file completion. However, there does not seem to be way
|
||||
# to tell tcsh to do that. To help the user, we try to simulate
|
||||
@ -85,19 +93,20 @@ else
|
||||
# We don't support ~ expansion: too tricky.
|
||||
if [ "\${TO_COMPLETE:0:1}" != "~" ]; then
|
||||
# Use ls so as to add the '/' at the end of directories.
|
||||
RESULT=(\`ls -dp \${TO_COMPLETE}* 2> /dev/null\`)
|
||||
echo \${RESULT[*]}
|
||||
|
||||
# If there is a single completion and it is a directory,
|
||||
# we output it a second time to trick tcsh into not adding a space
|
||||
# after it.
|
||||
if [ \${#RESULT[*]} -eq 1 ] && [ "\${RESULT[0]: -1}" == "/" ]; then
|
||||
echo \${RESULT[*]}
|
||||
fi
|
||||
COMPREPLY=(\`ls -dp \${TO_COMPLETE}* 2> /dev/null\`)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# tcsh does not automatically remove duplicates, so we do it ourselves
|
||||
echo "\${COMPREPLY[*]}" | sort | uniq
|
||||
|
||||
# If there is a single completion and it is a directory, we output it
|
||||
# a second time to trick tcsh into not adding a space after it.
|
||||
if [ \${#COMPREPLY[*]} -eq 1 ] && [ "\${COMPREPLY[0]: -1}" == "/" ]; then
|
||||
echo "\${COMPREPLY[*]}"
|
||||
fi
|
||||
|
||||
EOF
|
||||
|
||||
# Don't need this variable anymore, so don't pollute the users environment
|
||||
|
@ -17,16 +17,6 @@ To install:
|
||||
|
||||
1. Copy these files to vim's syntax directory $HOME/.vim/syntax
|
||||
2. To auto-detect the editing of various git-related filetypes:
|
||||
$ cat >>$HOME/.vim/filetype.vim <<'EOF'
|
||||
autocmd BufNewFile,BufRead *.git/COMMIT_EDITMSG setf gitcommit
|
||||
autocmd BufNewFile,BufRead *.git/config,.gitconfig setf gitconfig
|
||||
autocmd BufNewFile,BufRead git-rebase-todo setf gitrebase
|
||||
autocmd BufNewFile,BufRead .msg.[0-9]*
|
||||
\ if getline(1) =~ '^From.*# This line is ignored.$' |
|
||||
\ setf gitsendemail |
|
||||
\ endif
|
||||
autocmd BufNewFile,BufRead *.git/**
|
||||
\ if getline(1) =~ '^\x\{40\}\>\|^ref: ' |
|
||||
\ setf git |
|
||||
\ endif
|
||||
EOF
|
||||
|
||||
$ curl http://ftp.vim.org/pub/vim/runtime/filetype.vim |
|
||||
sed -ne '/^" Git$/, /^$/ p' >>$HOME/.vim/filetype.vim
|
||||
|
97
dir.c
97
dir.c
@ -732,7 +732,8 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
|
||||
|
||||
static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
|
||||
{
|
||||
if (cache_name_exists(pathname, len, ignore_case))
|
||||
if (!(dir->flags & DIR_SHOW_IGNORED) &&
|
||||
cache_name_exists(pathname, len, ignore_case))
|
||||
return NULL;
|
||||
|
||||
ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
|
||||
@ -834,8 +835,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
|
||||
* traversal routine.
|
||||
*
|
||||
* Case 1: If we *already* have entries in the index under that
|
||||
* directory name, we always recurse into the directory to see
|
||||
* all the files.
|
||||
* directory name, we recurse into the directory to see all the files,
|
||||
* unless the directory is excluded and we want to show ignored
|
||||
* directories
|
||||
*
|
||||
* Case 2: If we *already* have that directory name as a gitlink,
|
||||
* we always continue to see it as a gitlink, regardless of whether
|
||||
@ -849,6 +851,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
|
||||
* just a directory, unless "hide_empty_directories" is
|
||||
* also true and the directory is empty, in which case
|
||||
* we just ignore it entirely.
|
||||
* if we are looking for ignored directories, look if it
|
||||
* contains only ignored files to decide if it must be shown as
|
||||
* ignored or not.
|
||||
* (b) if it looks like a git directory, and we don't have
|
||||
* 'no_gitlinks' set we treat it as a gitlink, and show it
|
||||
* as a directory.
|
||||
@ -861,12 +866,15 @@ enum directory_treatment {
|
||||
};
|
||||
|
||||
static enum directory_treatment treat_directory(struct dir_struct *dir,
|
||||
const char *dirname, int len,
|
||||
const char *dirname, int len, int exclude,
|
||||
const struct path_simplify *simplify)
|
||||
{
|
||||
/* The "len-1" is to strip the final '/' */
|
||||
switch (directory_exists_in_index(dirname, len-1)) {
|
||||
case index_directory:
|
||||
if ((dir->flags & DIR_SHOW_OTHER_DIRECTORIES) && exclude)
|
||||
break;
|
||||
|
||||
return recurse_into_directory;
|
||||
|
||||
case index_gitdir:
|
||||
@ -886,13 +894,68 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
|
||||
}
|
||||
|
||||
/* This is the "show_other_directories" case */
|
||||
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
|
||||
|
||||
/*
|
||||
* We are looking for ignored files and our directory is not ignored,
|
||||
* check if it contains only ignored files
|
||||
*/
|
||||
if ((dir->flags & DIR_SHOW_IGNORED) && !exclude) {
|
||||
int ignored;
|
||||
dir->flags &= ~DIR_SHOW_IGNORED;
|
||||
dir->flags |= DIR_HIDE_EMPTY_DIRECTORIES;
|
||||
ignored = read_directory_recursive(dir, dirname, len, 1, simplify);
|
||||
dir->flags &= ~DIR_HIDE_EMPTY_DIRECTORIES;
|
||||
dir->flags |= DIR_SHOW_IGNORED;
|
||||
|
||||
return ignored ? ignore_directory : show_directory;
|
||||
}
|
||||
if (!(dir->flags & DIR_SHOW_IGNORED) &&
|
||||
!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
|
||||
return show_directory;
|
||||
if (!read_directory_recursive(dir, dirname, len, 1, simplify))
|
||||
return ignore_directory;
|
||||
return show_directory;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide what to do when we find a file while traversing the
|
||||
* filesystem. Mostly two cases:
|
||||
*
|
||||
* 1. We are looking for ignored files
|
||||
* (a) File is ignored, include it
|
||||
* (b) File is in ignored path, include it
|
||||
* (c) File is not ignored, exclude it
|
||||
*
|
||||
* 2. Other scenarios, include the file if not excluded
|
||||
*
|
||||
* Return 1 for exclude, 0 for include.
|
||||
*/
|
||||
static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude, int *dtype)
|
||||
{
|
||||
struct path_exclude_check check;
|
||||
int exclude_file = 0;
|
||||
|
||||
if (exclude)
|
||||
exclude_file = !(dir->flags & DIR_SHOW_IGNORED);
|
||||
else if (dir->flags & DIR_SHOW_IGNORED) {
|
||||
/* Always exclude indexed files */
|
||||
struct cache_entry *ce = index_name_exists(&the_index,
|
||||
path->buf, path->len, ignore_case);
|
||||
|
||||
if (ce)
|
||||
return 1;
|
||||
|
||||
path_exclude_check_init(&check, dir);
|
||||
|
||||
if (!path_excluded(&check, path->buf, path->len, dtype))
|
||||
exclude_file = 1;
|
||||
|
||||
path_exclude_check_clear(&check);
|
||||
}
|
||||
|
||||
return exclude_file;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an inexact early pruning of any recursive directory
|
||||
* reading - if the path cannot possibly be in the pathspec,
|
||||
@ -1031,27 +1094,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||
if (dtype == DT_UNKNOWN)
|
||||
dtype = get_dtype(de, path->buf, path->len);
|
||||
|
||||
/*
|
||||
* Do we want to see just the ignored files?
|
||||
* We still need to recurse into directories,
|
||||
* even if we don't ignore them, since the
|
||||
* directory may contain files that we do..
|
||||
*/
|
||||
if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
|
||||
if (dtype != DT_DIR)
|
||||
return path_ignored;
|
||||
}
|
||||
|
||||
switch (dtype) {
|
||||
default:
|
||||
return path_ignored;
|
||||
case DT_DIR:
|
||||
strbuf_addch(path, '/');
|
||||
switch (treat_directory(dir, path->buf, path->len, simplify)) {
|
||||
|
||||
switch (treat_directory(dir, path->buf, path->len, exclude, simplify)) {
|
||||
case show_directory:
|
||||
if (exclude != !!(dir->flags
|
||||
& DIR_SHOW_IGNORED))
|
||||
return path_ignored;
|
||||
break;
|
||||
case recurse_into_directory:
|
||||
return path_recurse;
|
||||
@ -1061,7 +1111,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||
break;
|
||||
case DT_REG:
|
||||
case DT_LNK:
|
||||
break;
|
||||
switch (treat_file(dir, path, exclude, &dtype)) {
|
||||
case 1:
|
||||
return path_ignored;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return path_handled;
|
||||
}
|
||||
|
@ -1285,10 +1285,10 @@ foreach my $t (@files) {
|
||||
}
|
||||
|
||||
if (defined $input_format && $input_format eq 'mbox') {
|
||||
if (/^Subject:\s+(.*)$/) {
|
||||
if (/^Subject:\s+(.*)$/i) {
|
||||
$subject = $1;
|
||||
}
|
||||
elsif (/^From:\s+(.*)$/) {
|
||||
elsif (/^From:\s+(.*)$/i) {
|
||||
($author, $author_encoding) = unquote_rfc2047($1);
|
||||
next if $suppress_cc{'author'};
|
||||
next if $suppress_cc{'self'} and $author eq $sender;
|
||||
@ -1296,14 +1296,14 @@ foreach my $t (@files) {
|
||||
$1, $_) unless $quiet;
|
||||
push @cc, $1;
|
||||
}
|
||||
elsif (/^To:\s+(.*)$/) {
|
||||
elsif (/^To:\s+(.*)$/i) {
|
||||
foreach my $addr (parse_address_line($1)) {
|
||||
printf("(mbox) Adding to: %s from line '%s'\n",
|
||||
$addr, $_) unless $quiet;
|
||||
push @to, $addr;
|
||||
}
|
||||
}
|
||||
elsif (/^Cc:\s+(.*)$/) {
|
||||
elsif (/^Cc:\s+(.*)$/i) {
|
||||
foreach my $addr (parse_address_line($1)) {
|
||||
if (unquote_rfc2047($addr) eq $sender) {
|
||||
next if ($suppress_cc{'self'});
|
||||
@ -1325,7 +1325,7 @@ foreach my $t (@files) {
|
||||
elsif (/^Message-Id: (.*)/i) {
|
||||
$message_id = $1;
|
||||
}
|
||||
elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) {
|
||||
elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
|
||||
push @xh, $_;
|
||||
}
|
||||
|
||||
|
46
path.c
46
path.c
@ -12,6 +12,7 @@
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "strbuf.h"
|
||||
#include "string-list.h"
|
||||
|
||||
static char bad_path[] = "/bad-path/";
|
||||
|
||||
@ -569,43 +570,38 @@ int normalize_path_copy(char *dst, const char *src)
|
||||
|
||||
/*
|
||||
* path = Canonical absolute path
|
||||
* prefix_list = Colon-separated list of absolute paths
|
||||
* prefixes = string_list containing normalized, absolute paths without
|
||||
* trailing slashes (except for the root directory, which is denoted by "/").
|
||||
*
|
||||
* Determines, for each path in prefix_list, whether the "prefix" really
|
||||
* Determines, for each path in prefixes, whether the "prefix"
|
||||
* is an ancestor directory of path. Returns the length of the longest
|
||||
* ancestor directory, excluding any trailing slashes, or -1 if no prefix
|
||||
* is an ancestor. (Note that this means 0 is returned if prefix_list is
|
||||
* "/".) "/foo" is not considered an ancestor of "/foobar". Directories
|
||||
* is an ancestor. (Note that this means 0 is returned if prefixes is
|
||||
* ["/"].) "/foo" is not considered an ancestor of "/foobar". Directories
|
||||
* are not considered to be their own ancestors. path must be in a
|
||||
* canonical form: empty components, or "." or ".." components are not
|
||||
* allowed. prefix_list may be null, which is like "".
|
||||
* allowed.
|
||||
*/
|
||||
int longest_ancestor_length(const char *path, const char *prefix_list)
|
||||
int longest_ancestor_length(const char *path, struct string_list *prefixes)
|
||||
{
|
||||
char buf[PATH_MAX+1];
|
||||
const char *ceil, *colon;
|
||||
int len, max_len = -1;
|
||||
int i, max_len = -1;
|
||||
|
||||
if (prefix_list == NULL || !strcmp(path, "/"))
|
||||
if (!strcmp(path, "/"))
|
||||
return -1;
|
||||
|
||||
for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
|
||||
for (colon = ceil; *colon && *colon != PATH_SEP; colon++);
|
||||
len = colon - ceil;
|
||||
if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
|
||||
continue;
|
||||
strlcpy(buf, ceil, len+1);
|
||||
if (normalize_path_copy(buf, buf) < 0)
|
||||
continue;
|
||||
len = strlen(buf);
|
||||
if (len > 0 && buf[len-1] == '/')
|
||||
buf[--len] = '\0';
|
||||
for (i = 0; i < prefixes->nr; i++) {
|
||||
const char *ceil = prefixes->items[i].string;
|
||||
int len = strlen(ceil);
|
||||
|
||||
if (!strncmp(path, buf, len) &&
|
||||
path[len] == '/' &&
|
||||
len > max_len) {
|
||||
if (len == 1 && ceil[0] == '/')
|
||||
len = 0; /* root matches anything, with length 0 */
|
||||
else if (!strncmp(path, ceil, len) && path[len] == '/')
|
||||
; /* match of length len */
|
||||
else
|
||||
continue; /* no match */
|
||||
|
||||
if (len > max_len)
|
||||
max_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
return max_len;
|
||||
|
34
setup.c
34
setup.c
@ -1,5 +1,6 @@
|
||||
#include "cache.h"
|
||||
#include "dir.h"
|
||||
#include "string-list.h"
|
||||
|
||||
static int inside_git_dir = -1;
|
||||
static int inside_work_tree = -1;
|
||||
@ -620,6 +621,27 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
|
||||
return buf.st_dev;
|
||||
}
|
||||
|
||||
/*
|
||||
* A "string_list_each_func_t" function that canonicalizes an entry
|
||||
* from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or
|
||||
* discards it if unusable.
|
||||
*/
|
||||
static int canonicalize_ceiling_entry(struct string_list_item *item,
|
||||
void *unused)
|
||||
{
|
||||
char *ceil = item->string;
|
||||
const char *real_path;
|
||||
|
||||
if (!*ceil || !is_absolute_path(ceil))
|
||||
return 0;
|
||||
real_path = real_path_if_valid(ceil);
|
||||
if (!real_path)
|
||||
return 0;
|
||||
free(item->string);
|
||||
item->string = xstrdup(real_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We cannot decide in this function whether we are in the work tree or
|
||||
* not, since the config can only be read _after_ this function was called.
|
||||
@ -627,10 +649,11 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
|
||||
static const char *setup_git_directory_gently_1(int *nongit_ok)
|
||||
{
|
||||
const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
|
||||
struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
|
||||
static char cwd[PATH_MAX+1];
|
||||
const char *gitdirenv, *ret;
|
||||
char *gitfile;
|
||||
int len, offset, offset_parent, ceil_offset;
|
||||
int len, offset, offset_parent, ceil_offset = -1;
|
||||
dev_t current_device = 0;
|
||||
int one_filesystem = 1;
|
||||
|
||||
@ -655,7 +678,14 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
|
||||
if (gitdirenv)
|
||||
return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
|
||||
|
||||
ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
|
||||
if (env_ceiling_dirs) {
|
||||
string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
|
||||
filter_string_list(&ceiling_dirs, 0,
|
||||
canonicalize_ceiling_entry, NULL);
|
||||
ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
|
||||
string_list_clear(&ceiling_dirs, 0);
|
||||
}
|
||||
|
||||
if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
|
||||
ceil_offset = 1;
|
||||
|
||||
|
@ -145,26 +145,6 @@ void string_list_remove_empty_items(struct string_list *list, int free_util) {
|
||||
filter_string_list(list, free_util, item_is_not_empty, NULL);
|
||||
}
|
||||
|
||||
char *string_list_longest_prefix(const struct string_list *prefixes,
|
||||
const char *string)
|
||||
{
|
||||
int i, max_len = -1;
|
||||
char *retval = NULL;
|
||||
|
||||
for (i = 0; i < prefixes->nr; i++) {
|
||||
char *prefix = prefixes->items[i].string;
|
||||
if (!prefixcmp(string, prefix)) {
|
||||
int len = strlen(prefix);
|
||||
if (len > max_len) {
|
||||
retval = prefix;
|
||||
max_len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void string_list_clear(struct string_list *list, int free_util)
|
||||
{
|
||||
if (list->items) {
|
||||
|
@ -45,15 +45,6 @@ void filter_string_list(struct string_list *list, int free_util,
|
||||
*/
|
||||
void string_list_remove_empty_items(struct string_list *list, int free_util);
|
||||
|
||||
/*
|
||||
* Return the longest string in prefixes that is a prefix (in the
|
||||
* sense of prefixcmp()) of string, or NULL if no such prefix exists.
|
||||
* This function does not require the string_list to be sorted (it
|
||||
* does a linear search).
|
||||
*/
|
||||
char *string_list_longest_prefix(const struct string_list *prefixes, const char *string);
|
||||
|
||||
|
||||
/* Use these functions only on sorted lists: */
|
||||
int string_list_has_string(const struct string_list *list, const char *string);
|
||||
int string_list_find_insert_index(const struct string_list *list, const char *string,
|
||||
|
@ -3,7 +3,12 @@
|
||||
test_description='respect crlf in git archive'
|
||||
|
||||
. ./test-lib.sh
|
||||
UNZIP=${UNZIP:-unzip}
|
||||
GIT_UNZIP=${GIT_UNZIP:-unzip}
|
||||
|
||||
test_lazy_prereq UNZIP '
|
||||
"$GIT_UNZIP" -v
|
||||
test $? -ne 127
|
||||
'
|
||||
|
||||
test_expect_success setup '
|
||||
|
||||
@ -26,18 +31,11 @@ test_expect_success 'tar archive' '
|
||||
|
||||
'
|
||||
|
||||
"$UNZIP" -v >/dev/null 2>&1
|
||||
if [ $? -eq 127 ]; then
|
||||
say "Skipping ZIP test, because unzip was not found"
|
||||
else
|
||||
test_set_prereq UNZIP
|
||||
fi
|
||||
|
||||
test_expect_success UNZIP 'zip archive' '
|
||||
|
||||
git archive --format=zip HEAD >test.zip &&
|
||||
|
||||
( mkdir unzipped && cd unzipped && unzip ../test.zip ) &&
|
||||
( mkdir unzipped && cd unzipped && "$GIT_UNZIP" ../test.zip ) &&
|
||||
|
||||
test_cmp sample unzipped/sample
|
||||
|
||||
|
@ -93,47 +93,32 @@ norm_path /d1/s1//../s2/../../d2 /d2 POSIX
|
||||
norm_path /d1/.../d2 /d1/.../d2 POSIX
|
||||
norm_path /d1/..././../d2 /d1/d2 POSIX
|
||||
|
||||
ancestor / "" -1
|
||||
ancestor / / -1
|
||||
ancestor /foo "" -1
|
||||
ancestor /foo : -1
|
||||
ancestor /foo ::. -1
|
||||
ancestor /foo ::..:: -1
|
||||
ancestor /foo / 0
|
||||
ancestor /foo /fo -1
|
||||
ancestor /foo /foo -1
|
||||
ancestor /foo /foo/ -1
|
||||
ancestor /foo /bar -1
|
||||
ancestor /foo /bar/ -1
|
||||
ancestor /foo /foo/bar -1
|
||||
ancestor /foo /foo:/bar/ -1
|
||||
ancestor /foo /foo/:/bar/ -1
|
||||
ancestor /foo /foo::/bar/ -1
|
||||
ancestor /foo /:/foo:/bar/ 0
|
||||
ancestor /foo /foo:/:/bar/ 0
|
||||
ancestor /foo /:/bar/:/foo 0
|
||||
ancestor /foo/bar "" -1
|
||||
ancestor /foo /foo:/bar -1
|
||||
ancestor /foo /:/foo:/bar 0
|
||||
ancestor /foo /foo:/:/bar 0
|
||||
ancestor /foo /:/bar:/foo 0
|
||||
ancestor /foo/bar / 0
|
||||
ancestor /foo/bar /fo -1
|
||||
ancestor /foo/bar foo -1
|
||||
ancestor /foo/bar /foo 4
|
||||
ancestor /foo/bar /foo/ 4
|
||||
ancestor /foo/bar /foo/ba -1
|
||||
ancestor /foo/bar /:/fo 0
|
||||
ancestor /foo/bar /foo:/foo/ba 4
|
||||
ancestor /foo/bar /bar -1
|
||||
ancestor /foo/bar /bar/ -1
|
||||
ancestor /foo/bar /fo: -1
|
||||
ancestor /foo/bar :/fo -1
|
||||
ancestor /foo/bar /foo:/bar/ 4
|
||||
ancestor /foo/bar /:/foo:/bar/ 4
|
||||
ancestor /foo/bar /foo:/:/bar/ 4
|
||||
ancestor /foo/bar /:/bar/:/fo 0
|
||||
ancestor /foo/bar /:/bar/ 0
|
||||
ancestor /foo/bar .:/foo/. 4
|
||||
ancestor /foo/bar .:/foo/.:.: 4
|
||||
ancestor /foo/bar /foo/./:.:/bar 4
|
||||
ancestor /foo/bar .:/bar -1
|
||||
ancestor /foo/bar /fo -1
|
||||
ancestor /foo/bar /foo:/bar 4
|
||||
ancestor /foo/bar /:/foo:/bar 4
|
||||
ancestor /foo/bar /foo:/:/bar 4
|
||||
ancestor /foo/bar /:/bar:/fo 0
|
||||
ancestor /foo/bar /:/bar 0
|
||||
ancestor /foo/bar /foo 4
|
||||
ancestor /foo/bar /foo:/bar 4
|
||||
ancestor /foo/bar /bar -1
|
||||
|
||||
test_expect_success 'strip_path_suffix' '
|
||||
test c:/msysgit = $(test-path-utils strip_path_suffix \
|
||||
|
@ -17,14 +17,6 @@ test_split () {
|
||||
"
|
||||
}
|
||||
|
||||
test_longest_prefix () {
|
||||
test "$(test-string-list longest_prefix "$1" "$2")" = "$3"
|
||||
}
|
||||
|
||||
test_no_longest_prefix () {
|
||||
test_must_fail test-string-list longest_prefix "$1" "$2"
|
||||
}
|
||||
|
||||
test_split "foo:bar:baz" ":" "-1" <<EOF
|
||||
3
|
||||
[0]: "foo"
|
||||
@ -96,26 +88,4 @@ test_expect_success "test remove_duplicates" '
|
||||
test a:b:c = "$(test-string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
|
||||
'
|
||||
|
||||
test_expect_success "test longest_prefix" '
|
||||
test_no_longest_prefix - '' &&
|
||||
test_no_longest_prefix - x &&
|
||||
test_longest_prefix "" x "" &&
|
||||
test_longest_prefix x x x &&
|
||||
test_longest_prefix "" foo "" &&
|
||||
test_longest_prefix : foo "" &&
|
||||
test_longest_prefix f foo f &&
|
||||
test_longest_prefix foo foobar foo &&
|
||||
test_longest_prefix foo foo foo &&
|
||||
test_no_longest_prefix bar foo &&
|
||||
test_no_longest_prefix bar:bar foo &&
|
||||
test_no_longest_prefix foobar foo &&
|
||||
test_longest_prefix foo:bar foo foo &&
|
||||
test_longest_prefix foo:bar bar bar &&
|
||||
test_longest_prefix foo::bar foo foo &&
|
||||
test_longest_prefix foo:foobar foo foo &&
|
||||
test_longest_prefix foobar:foo foo foo &&
|
||||
test_longest_prefix foo: bar "" &&
|
||||
test_longest_prefix :foo bar ""
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -25,32 +25,11 @@ commit id embedding:
|
||||
'
|
||||
|
||||
. ./test-lib.sh
|
||||
UNZIP=${UNZIP:-unzip}
|
||||
GZIP=${GZIP:-gzip}
|
||||
GUNZIP=${GUNZIP:-gzip -d}
|
||||
|
||||
SUBSTFORMAT=%H%n
|
||||
|
||||
check_zip() {
|
||||
zipfile=$1.zip
|
||||
listfile=$1.lst
|
||||
dir=$1
|
||||
dir_with_prefix=$dir/$2
|
||||
|
||||
test_expect_success UNZIP " extract ZIP archive" "
|
||||
(mkdir $dir && cd $dir && $UNZIP ../$zipfile)
|
||||
"
|
||||
|
||||
test_expect_success UNZIP " validate filenames" "
|
||||
(cd ${dir_with_prefix}a && find .) | sort >$listfile &&
|
||||
test_cmp a.lst $listfile
|
||||
"
|
||||
|
||||
test_expect_success UNZIP " validate file contents" "
|
||||
diff -r a ${dir_with_prefix}a
|
||||
"
|
||||
}
|
||||
|
||||
test_expect_success \
|
||||
'populate workdir' \
|
||||
'mkdir a b c &&
|
||||
@ -201,61 +180,11 @@ test_expect_success \
|
||||
test_cmp a/substfile2 g/prefix/a/substfile2
|
||||
'
|
||||
|
||||
$UNZIP -v >/dev/null 2>&1
|
||||
if [ $? -eq 127 ]; then
|
||||
say "Skipping ZIP tests, because unzip was not found"
|
||||
else
|
||||
test_set_prereq UNZIP
|
||||
fi
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip' \
|
||||
'git archive --format=zip HEAD >d.zip'
|
||||
|
||||
check_zip d
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip in a bare repo' \
|
||||
'(cd bare.git && git archive --format=zip HEAD) >d1.zip'
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip vs. the same in a bare repo' \
|
||||
'test_cmp d.zip d1.zip'
|
||||
|
||||
test_expect_success 'git archive --format=zip with --output' \
|
||||
'git archive --format=zip --output=d2.zip HEAD &&
|
||||
test_cmp d.zip d2.zip'
|
||||
|
||||
test_expect_success 'git archive with --output, inferring format' '
|
||||
git archive --output=d3.zip HEAD &&
|
||||
test_cmp d.zip d3.zip
|
||||
'
|
||||
|
||||
test_expect_success 'git archive with --output, override inferred format' '
|
||||
git archive --format=tar --output=d4.zip HEAD &&
|
||||
test_cmp b.tar d4.zip
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip with prefix' \
|
||||
'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
|
||||
|
||||
check_zip e prefix/
|
||||
|
||||
test_expect_success 'git archive -0 --format=zip on large files' '
|
||||
test_config core.bigfilethreshold 1 &&
|
||||
git archive -0 --format=zip HEAD >large.zip
|
||||
'
|
||||
|
||||
check_zip large
|
||||
|
||||
test_expect_success 'git archive --format=zip on large files' '
|
||||
test_config core.bigfilethreshold 1 &&
|
||||
git archive --format=zip HEAD >large-compressed.zip
|
||||
'
|
||||
|
||||
check_zip large-compressed
|
||||
|
||||
test_expect_success \
|
||||
'git archive --list outside of a git repo' \
|
||||
'GIT_DIR=some/non-existing/directory git archive --list'
|
||||
|
131
t/t5003-archive-zip.sh
Executable file
131
t/t5003-archive-zip.sh
Executable file
@ -0,0 +1,131 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='git archive --format=zip test'
|
||||
|
||||
. ./test-lib.sh
|
||||
GIT_UNZIP=${GIT_UNZIP:-unzip}
|
||||
|
||||
SUBSTFORMAT=%H%n
|
||||
|
||||
test_lazy_prereq UNZIP '
|
||||
"$GIT_UNZIP" -v
|
||||
test $? -ne 127
|
||||
'
|
||||
|
||||
test_lazy_prereq UNZIP_SYMLINKS '
|
||||
(
|
||||
mkdir unzip-symlinks &&
|
||||
cd unzip-symlinks &&
|
||||
"$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip &&
|
||||
test -h symlink
|
||||
)
|
||||
'
|
||||
|
||||
check_zip() {
|
||||
zipfile=$1.zip
|
||||
listfile=$1.lst
|
||||
dir=$1
|
||||
dir_with_prefix=$dir/$2
|
||||
|
||||
test_expect_success UNZIP " extract ZIP archive" '
|
||||
(mkdir $dir && cd $dir && "$GIT_UNZIP" ../$zipfile)
|
||||
'
|
||||
|
||||
test_expect_success UNZIP " validate filenames" "
|
||||
(cd ${dir_with_prefix}a && find .) | sort >$listfile &&
|
||||
test_cmp a.lst $listfile
|
||||
"
|
||||
|
||||
test_expect_success UNZIP " validate file contents" "
|
||||
diff -r a ${dir_with_prefix}a
|
||||
"
|
||||
}
|
||||
|
||||
test_expect_success \
|
||||
'populate workdir' \
|
||||
'mkdir a b c &&
|
||||
echo simple textfile >a/a &&
|
||||
mkdir a/bin &&
|
||||
cp /bin/sh a/bin &&
|
||||
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
|
||||
printf "A not substituted O" >a/substfile2 &&
|
||||
(p=long_path_to_a_file && cd a &&
|
||||
for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
|
||||
echo text >file_with_long_path)
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS,UNZIP_SYMLINKS 'add symlink' '
|
||||
ln -s a a/symlink_to_a
|
||||
'
|
||||
|
||||
test_expect_success 'prepare file list' '
|
||||
(cd a && find .) | sort >a.lst
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'add ignored file' \
|
||||
'echo ignore me >a/ignored &&
|
||||
echo ignored export-ignore >.git/info/attributes'
|
||||
|
||||
test_expect_success \
|
||||
'add files to repository' \
|
||||
'find a -type f | xargs git update-index --add &&
|
||||
find a -type l | xargs git update-index --add &&
|
||||
treeid=`git write-tree` &&
|
||||
echo $treeid >treeid &&
|
||||
git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
|
||||
git commit-tree $treeid </dev/null)'
|
||||
|
||||
test_expect_success \
|
||||
'create bare clone' \
|
||||
'git clone --bare . bare.git &&
|
||||
cp .git/info/attributes bare.git/info/attributes'
|
||||
|
||||
test_expect_success \
|
||||
'remove ignored file' \
|
||||
'rm a/ignored'
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip' \
|
||||
'git archive --format=zip HEAD >d.zip'
|
||||
|
||||
check_zip d
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip in a bare repo' \
|
||||
'(cd bare.git && git archive --format=zip HEAD) >d1.zip'
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip vs. the same in a bare repo' \
|
||||
'test_cmp d.zip d1.zip'
|
||||
|
||||
test_expect_success 'git archive --format=zip with --output' \
|
||||
'git archive --format=zip --output=d2.zip HEAD &&
|
||||
test_cmp d.zip d2.zip'
|
||||
|
||||
test_expect_success 'git archive with --output, inferring format' '
|
||||
git archive --output=d3.zip HEAD &&
|
||||
test_cmp d.zip d3.zip
|
||||
'
|
||||
|
||||
test_expect_success \
|
||||
'git archive --format=zip with prefix' \
|
||||
'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
|
||||
|
||||
check_zip e prefix/
|
||||
|
||||
test_expect_success 'git archive -0 --format=zip on large files' '
|
||||
test_config core.bigfilethreshold 1 &&
|
||||
git archive -0 --format=zip HEAD >large.zip
|
||||
'
|
||||
|
||||
check_zip large
|
||||
|
||||
test_expect_success 'git archive --format=zip on large files' '
|
||||
test_config core.bigfilethreshold 1 &&
|
||||
git archive --format=zip HEAD >large-compressed.zip
|
||||
'
|
||||
|
||||
check_zip large-compressed
|
||||
|
||||
test_done
|
BIN
t/t5003/infozip-symlinks.zip
Normal file
BIN
t/t5003/infozip-symlinks.zip
Normal file
Binary file not shown.
146
t/t7061-wtstatus-ignore.sh
Executable file
146
t/t7061-wtstatus-ignore.sh
Executable file
@ -0,0 +1,146 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='git-status ignored files'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
?? untracked/
|
||||
EOF
|
||||
|
||||
test_expect_success 'status untracked directory with --ignored' '
|
||||
echo "ignored" >.gitignore &&
|
||||
mkdir untracked &&
|
||||
: >untracked/ignored &&
|
||||
: >untracked/uncommitted &&
|
||||
git status --porcelain --ignored >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
?? untracked/uncommitted
|
||||
!! untracked/ignored
|
||||
EOF
|
||||
|
||||
test_expect_success 'status untracked directory with --ignored -u' '
|
||||
git status --porcelain --ignored -u >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
!! ignored/
|
||||
EOF
|
||||
|
||||
test_expect_success 'status ignored directory with --ignore' '
|
||||
rm -rf untracked &&
|
||||
mkdir ignored &&
|
||||
: >ignored/uncommitted &&
|
||||
git status --porcelain --ignored >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
!! ignored/uncommitted
|
||||
EOF
|
||||
|
||||
test_expect_success 'status ignored directory with --ignore -u' '
|
||||
git status --porcelain --ignored -u >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
!! untracked-ignored/
|
||||
EOF
|
||||
|
||||
test_expect_success 'status untracked directory with ignored files with --ignore' '
|
||||
rm -rf ignored &&
|
||||
mkdir untracked-ignored &&
|
||||
mkdir untracked-ignored/test &&
|
||||
: >untracked-ignored/ignored &&
|
||||
: >untracked-ignored/test/ignored &&
|
||||
git status --porcelain --ignored >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
!! untracked-ignored/ignored
|
||||
!! untracked-ignored/test/ignored
|
||||
EOF
|
||||
|
||||
test_expect_success 'status untracked directory with ignored files with --ignore -u' '
|
||||
git status --porcelain --ignored -u >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
EOF
|
||||
|
||||
test_expect_success 'status ignored tracked directory with --ignore' '
|
||||
rm -rf untracked-ignored &&
|
||||
mkdir tracked &&
|
||||
: >tracked/committed &&
|
||||
git add tracked/committed &&
|
||||
git commit -m. &&
|
||||
echo "tracked" >.gitignore &&
|
||||
git status --porcelain --ignored >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
EOF
|
||||
|
||||
test_expect_success 'status ignored tracked directory with --ignore -u' '
|
||||
git status --porcelain --ignored -u >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
!! tracked/
|
||||
EOF
|
||||
|
||||
test_expect_success 'status ignored tracked directory and uncommitted file with --ignore' '
|
||||
: >tracked/uncommitted &&
|
||||
git status --porcelain --ignored >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
cat >expected <<\EOF
|
||||
?? .gitignore
|
||||
?? actual
|
||||
?? expected
|
||||
!! tracked/uncommitted
|
||||
EOF
|
||||
|
||||
test_expect_success 'status ignored tracked directory and uncommitted file with --ignore -u' '
|
||||
git status --porcelain --ignored -u >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_done
|
@ -85,6 +85,7 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
|
||||
.*_TEST
|
||||
PROVE
|
||||
VALGRIND
|
||||
UNZIP
|
||||
PERF_AGGREGATING_LATER
|
||||
));
|
||||
my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
|
||||
@ -128,6 +129,7 @@ fi
|
||||
unset CDPATH
|
||||
|
||||
unset GREP_OPTIONS
|
||||
unset UNZIP
|
||||
|
||||
case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
|
||||
1|2|true)
|
||||
|
@ -1,4 +1,32 @@
|
||||
#include "cache.h"
|
||||
#include "string-list.h"
|
||||
|
||||
/*
|
||||
* A "string_list_each_func_t" function that normalizes an entry from
|
||||
* GIT_CEILING_DIRECTORIES. If the path is unusable for some reason,
|
||||
* die with an explanation.
|
||||
*/
|
||||
static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
|
||||
{
|
||||
const char *ceil = item->string;
|
||||
int len = strlen(ceil);
|
||||
char buf[PATH_MAX+1];
|
||||
|
||||
if (len == 0)
|
||||
die("Empty path is not supported");
|
||||
if (len > PATH_MAX)
|
||||
die("Path \"%s\" is too long", ceil);
|
||||
if (!is_absolute_path(ceil))
|
||||
die("Path \"%s\" is not absolute", ceil);
|
||||
if (normalize_path_copy(buf, ceil) < 0)
|
||||
die("Path \"%s\" could not be normalized", ceil);
|
||||
len = strlen(buf);
|
||||
if (len > 1 && buf[len-1] == '/')
|
||||
die("Normalized path \"%s\" ended with slash", buf);
|
||||
free(item->string);
|
||||
item->string = xstrdup(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -30,7 +58,28 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
|
||||
int len = longest_ancestor_length(argv[2], argv[3]);
|
||||
int len;
|
||||
struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
|
||||
char *path = xstrdup(argv[2]);
|
||||
|
||||
/*
|
||||
* We have to normalize the arguments because under
|
||||
* Windows, bash mangles arguments that look like
|
||||
* absolute POSIX paths or colon-separate lists of
|
||||
* absolute POSIX paths into DOS paths (e.g.,
|
||||
* "/foo:/foo/bar" might be converted to
|
||||
* "D:\Src\msysgit\foo;D:\Src\msysgit\foo\bar"),
|
||||
* whereas longest_ancestor_length() requires paths
|
||||
* that use forward slashes.
|
||||
*/
|
||||
if (normalize_path_copy(path, path))
|
||||
die("Path \"%s\" could not be normalized", argv[2]);
|
||||
string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
|
||||
filter_string_list(&ceiling_dirs, 0,
|
||||
normalize_ceiling_entry, NULL);
|
||||
len = longest_ancestor_length(path, &ceiling_dirs);
|
||||
string_list_clear(&ceiling_dirs, 0);
|
||||
free(path);
|
||||
printf("%d\n", len);
|
||||
return 0;
|
||||
}
|
||||
|
@ -97,26 +97,6 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 4 && !strcmp(argv[1], "longest_prefix")) {
|
||||
/* arguments: <colon-separated-prefixes>|- <string> */
|
||||
struct string_list prefixes = STRING_LIST_INIT_DUP;
|
||||
int retval;
|
||||
const char *prefix_string = argv[2];
|
||||
const char *string = argv[3];
|
||||
const char *match;
|
||||
|
||||
parse_string_list(&prefixes, prefix_string);
|
||||
match = string_list_longest_prefix(&prefixes, string);
|
||||
if (match) {
|
||||
printf("%s\n", match);
|
||||
retval = 0;
|
||||
}
|
||||
else
|
||||
retval = 1;
|
||||
string_list_clear(&prefixes, 0);
|
||||
return retval;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
|
||||
argv[1] ? argv[1] : "(there was none)");
|
||||
return 1;
|
||||
|
@ -516,7 +516,9 @@ static void wt_status_collect_untracked(struct wt_status *s)
|
||||
|
||||
if (s->show_ignored_files) {
|
||||
dir.nr = 0;
|
||||
dir.flags = DIR_SHOW_IGNORED | DIR_SHOW_OTHER_DIRECTORIES;
|
||||
dir.flags = DIR_SHOW_IGNORED;
|
||||
if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
|
||||
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
|
||||
fill_directory(&dir, s->pathspec);
|
||||
for (i = 0; i < dir.nr; i++) {
|
||||
struct dir_entry *ent = dir.entries[i];
|
||||
|
Reference in New Issue
Block a user