зеркало из https://github.com/microsoft/git.git
Merge branch 'dr/ceiling'
* dr/ceiling: Eliminate an unnecessary chdir("..") Add support for GIT_CEILING_DIRECTORIES Fold test-absolute-path into test-path-utils Implement normalize_absolute_path Conflicts: cache.h setup.c
This commit is contained in:
Коммит
17d778e710
|
@ -141,7 +141,6 @@ git-write-tree
|
|||
git-core-*/?*
|
||||
gitk-wish
|
||||
gitweb/gitweb.cgi
|
||||
test-absolute-path
|
||||
test-chmtime
|
||||
test-date
|
||||
test-delta
|
||||
|
@ -149,6 +148,7 @@ test-dump-cache-tree
|
|||
test-genrandom
|
||||
test-match-trees
|
||||
test-parse-options
|
||||
test-path-utils
|
||||
test-sha1
|
||||
common-cmds.h
|
||||
*.tar.gz
|
||||
|
|
|
@ -427,6 +427,14 @@ git so take care if using Cogito etc.
|
|||
This can also be controlled by the '--work-tree' command line
|
||||
option and the core.worktree configuration variable.
|
||||
|
||||
'GIT_CEILING_DIRECTORIES'::
|
||||
This should be a colon-separated list of absolute paths.
|
||||
If set, it is a list of directories that git should not chdir
|
||||
up into while looking for a repository directory.
|
||||
It will not exclude the current working directory or
|
||||
a GIT_DIR set on the command line or in the environment.
|
||||
(Useful for excluding slow-loading network directories.)
|
||||
|
||||
git Commits
|
||||
~~~~~~~~~~~
|
||||
'GIT_AUTHOR_NAME'::
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1265,7 +1265,7 @@ endif
|
|||
|
||||
### Testing rules
|
||||
|
||||
TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X
|
||||
TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
|
||||
|
||||
all:: $(TEST_PROGRAMS)
|
||||
|
||||
|
|
3
cache.h
3
cache.h
|
@ -299,6 +299,7 @@ static inline enum object_type object_type(unsigned int mode)
|
|||
#define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR"
|
||||
#define CONFIG_ENVIRONMENT "GIT_CONFIG"
|
||||
#define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
|
||||
#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
|
||||
#define GITATTRIBUTES_FILE ".gitattributes"
|
||||
#define INFOATTRIBUTES_FILE "info/attributes"
|
||||
#define ATTRIBUTE_MACRO_PREFIX "[attr]"
|
||||
|
@ -526,6 +527,8 @@ static inline int is_absolute_path(const char *path)
|
|||
const char *make_absolute_path(const char *path);
|
||||
const char *make_nonrelative_path(const char *path);
|
||||
const char *make_relative_path(const char *abs, const char *base);
|
||||
int normalize_absolute_path(char *buf, const char *path);
|
||||
int longest_ancestor_length(const char *path, const char *prefix_list);
|
||||
|
||||
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
|
||||
extern int sha1_object_info(const unsigned char *, unsigned long *);
|
||||
|
|
96
path.c
96
path.c
|
@ -343,3 +343,99 @@ const char *make_relative_path(const char *abs, const char *base)
|
|||
strcpy(buf, abs + baselen);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* path = absolute path
|
||||
* buf = buffer of at least max(2, strlen(path)+1) bytes
|
||||
* It is okay if buf == path, but they should not overlap otherwise.
|
||||
*
|
||||
* Performs the following normalizations on path, storing the result in buf:
|
||||
* - Removes trailing slashes.
|
||||
* - Removes empty components.
|
||||
* - Removes "." components.
|
||||
* - Removes ".." components, and the components the precede them.
|
||||
* "" and paths that contain only slashes are normalized to "/".
|
||||
* Returns the length of the output.
|
||||
*
|
||||
* Note that this function is purely textual. It does not follow symlinks,
|
||||
* verify the existence of the path, or make any system calls.
|
||||
*/
|
||||
int normalize_absolute_path(char *buf, const char *path)
|
||||
{
|
||||
const char *comp_start = path, *comp_end = path;
|
||||
char *dst = buf;
|
||||
int comp_len;
|
||||
assert(buf);
|
||||
assert(path);
|
||||
|
||||
while (*comp_start) {
|
||||
assert(*comp_start == '/');
|
||||
while (*++comp_end && *comp_end != '/')
|
||||
; /* nothing */
|
||||
comp_len = comp_end - comp_start;
|
||||
|
||||
if (!strncmp("/", comp_start, comp_len) ||
|
||||
!strncmp("/.", comp_start, comp_len))
|
||||
goto next;
|
||||
|
||||
if (!strncmp("/..", comp_start, comp_len)) {
|
||||
while (dst > buf && *--dst != '/')
|
||||
; /* nothing */
|
||||
goto next;
|
||||
}
|
||||
|
||||
memcpy(dst, comp_start, comp_len);
|
||||
dst += comp_len;
|
||||
next:
|
||||
comp_start = comp_end;
|
||||
}
|
||||
|
||||
if (dst == buf)
|
||||
*dst++ = '/';
|
||||
|
||||
*dst = '\0';
|
||||
return dst - buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* path = Canonical absolute path
|
||||
* prefix_list = Colon-separated list of absolute paths
|
||||
*
|
||||
* Determines, for each path in parent_list, whether the "prefix" really
|
||||
* 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
|
||||
* 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 "".
|
||||
*/
|
||||
int longest_ancestor_length(const char *path, const char *prefix_list)
|
||||
{
|
||||
char buf[PATH_MAX+1];
|
||||
const char *ceil, *colon;
|
||||
int len, max_len = -1;
|
||||
|
||||
if (prefix_list == NULL || !strcmp(path, "/"))
|
||||
return -1;
|
||||
|
||||
for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
|
||||
for (colon = ceil; *colon && *colon != ':'; colon++);
|
||||
len = colon - ceil;
|
||||
if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
|
||||
continue;
|
||||
strlcpy(buf, ceil, len+1);
|
||||
len = normalize_absolute_path(buf, buf);
|
||||
/* Strip "trailing slashes" from "/". */
|
||||
if (len == 1)
|
||||
len = 0;
|
||||
|
||||
if (!strncmp(path, buf, len) &&
|
||||
path[len] == '/' &&
|
||||
len > max_len) {
|
||||
max_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
return max_len;
|
||||
}
|
||||
|
|
31
setup.c
31
setup.c
|
@ -376,11 +376,11 @@ const char *read_gitfile_gently(const char *path)
|
|||
const char *setup_git_directory_gently(int *nongit_ok)
|
||||
{
|
||||
const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
|
||||
const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
|
||||
static char cwd[PATH_MAX+1];
|
||||
const char *gitdirenv;
|
||||
const char *gitfile_dir;
|
||||
int len, offset;
|
||||
int minoffset = 0;
|
||||
int len, offset, ceil_offset;
|
||||
|
||||
/*
|
||||
* Let's assume that we are in a git repository.
|
||||
|
@ -431,8 +431,10 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
|||
|
||||
if (!getcwd(cwd, sizeof(cwd)-1))
|
||||
die("Unable to read current working directory");
|
||||
if (has_dos_drive_prefix(cwd))
|
||||
minoffset = 2;
|
||||
|
||||
ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
|
||||
if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
|
||||
ceil_offset = 1;
|
||||
|
||||
/*
|
||||
* Test in the following order (relative to the cwd):
|
||||
|
@ -463,18 +465,17 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
|||
check_repository_format_gently(nongit_ok);
|
||||
return NULL;
|
||||
}
|
||||
chdir("..");
|
||||
do {
|
||||
if (offset <= minoffset) {
|
||||
if (nongit_ok) {
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
die("Not a git repository");
|
||||
while (--offset > ceil_offset && cwd[offset] != '/');
|
||||
if (offset <= ceil_offset) {
|
||||
if (nongit_ok) {
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
} while (offset > minoffset && cwd[--offset] != '/');
|
||||
die("Not a git repository");
|
||||
}
|
||||
chdir("..");
|
||||
}
|
||||
|
||||
inside_git_dir = 0;
|
||||
|
|
|
@ -301,14 +301,14 @@ test_expect_success 'absolute path works as expected' '
|
|||
mkdir third &&
|
||||
dir="$(cd .git; pwd -P)" &&
|
||||
dir2=third/../second/other/.git &&
|
||||
test "$dir" = "$(test-absolute-path $dir2)" &&
|
||||
test "$dir" = "$(test-path-utils make_absolute_path $dir2)" &&
|
||||
file="$dir"/index &&
|
||||
test "$file" = "$(test-absolute-path $dir2/index)" &&
|
||||
test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" &&
|
||||
basename=blub &&
|
||||
test "$dir/$basename" = "$(cd .git && test-absolute-path "$basename")" &&
|
||||
test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" &&
|
||||
ln -s ../first/file .git/syml &&
|
||||
sym="$(cd first; pwd -P)"/file &&
|
||||
test "$sym" = "$(test-absolute-path "$dir2/syml")"
|
||||
test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")"
|
||||
'
|
||||
|
||||
test_expect_success 'very long name in the index handled sanely' '
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2008 David Reiss
|
||||
#
|
||||
|
||||
test_description='Test various path utilities'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
norm_abs() {
|
||||
test_expect_success "normalize absolute" \
|
||||
"test \$(test-path-utils normalize_absolute_path '$1') = '$2'"
|
||||
}
|
||||
|
||||
ancestor() {
|
||||
test_expect_success "longest ancestor" \
|
||||
"test \$(test-path-utils longest_ancestor_length '$1' '$2') = '$3'"
|
||||
}
|
||||
|
||||
norm_abs "" /
|
||||
norm_abs / /
|
||||
norm_abs // /
|
||||
norm_abs /// /
|
||||
norm_abs /. /
|
||||
norm_abs /./ /
|
||||
norm_abs /./.. /
|
||||
norm_abs /../. /
|
||||
norm_abs /./../.// /
|
||||
norm_abs /dir/.. /
|
||||
norm_abs /dir/sub/../.. /
|
||||
norm_abs /dir /dir
|
||||
norm_abs /dir// /dir
|
||||
norm_abs /./dir /dir
|
||||
norm_abs /dir/. /dir
|
||||
norm_abs /dir///./ /dir
|
||||
norm_abs /dir//sub/.. /dir
|
||||
norm_abs /dir/sub/../ /dir
|
||||
norm_abs //dir/sub/../. /dir
|
||||
norm_abs /dir/s1/../s2/ /dir/s2
|
||||
norm_abs /d1/s1///s2/..//../s3/ /d1/s3
|
||||
norm_abs /d1/s1//../s2/../../d2 /d2
|
||||
norm_abs /d1/.../d2 /d1/.../d2
|
||||
norm_abs /d1/..././../d2 /d1/d2
|
||||
|
||||
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/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
|
||||
|
||||
test_done
|
|
@ -0,0 +1,163 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='test GIT_CEILING_DIRECTORIES'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_prefix() {
|
||||
test_expect_success "$1" \
|
||||
"test '$2' = \"\$(git rev-parse --show-prefix)\""
|
||||
}
|
||||
|
||||
test_fail() {
|
||||
test_expect_code 128 "$1: prefix" \
|
||||
"git rev-parse --show-prefix"
|
||||
}
|
||||
|
||||
TRASH_ROOT="$(pwd)"
|
||||
ROOT_PARENT=$(dirname "$TRASH_ROOT")
|
||||
|
||||
|
||||
unset GIT_CEILING_DIRECTORIES
|
||||
test_prefix no_ceil ""
|
||||
|
||||
export GIT_CEILING_DIRECTORIES
|
||||
|
||||
GIT_CEILING_DIRECTORIES=""
|
||||
test_prefix ceil_empty ""
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$ROOT_PARENT"
|
||||
test_prefix ceil_at_parent ""
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$ROOT_PARENT/"
|
||||
test_prefix ceil_at_parent_slash ""
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
|
||||
test_prefix ceil_at_trash ""
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
|
||||
test_prefix ceil_at_trash_slash ""
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
|
||||
test_prefix ceil_at_sub ""
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
|
||||
test_prefix ceil_at_sub_slash ""
|
||||
|
||||
|
||||
mkdir -p sub/dir || exit 1
|
||||
cd sub/dir || exit 1
|
||||
|
||||
unset GIT_CEILING_DIRECTORIES
|
||||
test_prefix subdir_no_ceil "sub/dir/"
|
||||
|
||||
export GIT_CEILING_DIRECTORIES
|
||||
|
||||
GIT_CEILING_DIRECTORIES=""
|
||||
test_prefix subdir_ceil_empty "sub/dir/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
|
||||
test_fail subdir_ceil_at_trash
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
|
||||
test_fail subdir_ceil_at_trash_slash
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
|
||||
test_fail subdir_ceil_at_sub
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
|
||||
test_fail subdir_ceil_at_sub_slash
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir"
|
||||
test_prefix subdir_ceil_at_subdir "sub/dir/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir/"
|
||||
test_prefix subdir_ceil_at_subdir_slash "sub/dir/"
|
||||
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
|
||||
test_prefix subdir_ceil_at_su "sub/dir/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
|
||||
test_prefix subdir_ceil_at_su_slash "sub/dir/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
|
||||
test_prefix subdir_ceil_at_sub_di "sub/dir/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
|
||||
test_prefix subdir_ceil_at_sub_di_slash "sub/dir/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
|
||||
test_prefix subdir_ceil_at_subdi "sub/dir/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
|
||||
test_prefix subdir_ceil_at_subdi_slash "sub/dir/"
|
||||
|
||||
|
||||
GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub"
|
||||
test_fail second_of_two
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:bar"
|
||||
test_fail first_of_two
|
||||
|
||||
GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub:bar"
|
||||
test_fail second_of_three
|
||||
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
|
||||
GIT_DIR=../../.git
|
||||
export GIT_DIR
|
||||
test_prefix git_dir_specified ""
|
||||
unset GIT_DIR
|
||||
|
||||
|
||||
cd ../.. || exit 1
|
||||
mkdir -p s/d || exit 1
|
||||
cd s/d || exit 1
|
||||
|
||||
unset GIT_CEILING_DIRECTORIES
|
||||
test_prefix sd_no_ceil "s/d/"
|
||||
|
||||
export GIT_CEILING_DIRECTORIES
|
||||
|
||||
GIT_CEILING_DIRECTORIES=""
|
||||
test_prefix sd_ceil_empty "s/d/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
|
||||
test_fail sd_ceil_at_trash
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
|
||||
test_fail sd_ceil_at_trash_slash
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s"
|
||||
test_fail sd_ceil_at_s
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/"
|
||||
test_fail sd_ceil_at_s_slash
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d"
|
||||
test_prefix sd_ceil_at_sd "s/d/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d/"
|
||||
test_prefix sd_ceil_at_sd_slash "s/d/"
|
||||
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
|
||||
test_prefix sd_ceil_at_su "s/d/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
|
||||
test_prefix sd_ceil_at_su_slash "s/d/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
|
||||
test_prefix sd_ceil_at_s_di "s/d/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
|
||||
test_prefix sd_ceil_at_s_di_slash "s/d/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
|
||||
test_prefix sd_ceil_at_sdi "s/d/"
|
||||
|
||||
GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
|
||||
test_prefix sd_ceil_at_sdi_slash "s/d/"
|
||||
|
||||
|
||||
test_done
|
|
@ -35,6 +35,7 @@ unset GIT_WORK_TREE
|
|||
unset GIT_EXTERNAL_DIFF
|
||||
unset GIT_INDEX_FILE
|
||||
unset GIT_OBJECT_DIRECTORY
|
||||
unset GIT_CEILING_DIRECTORIES
|
||||
unset SHA1_FILE_DIRECTORIES
|
||||
unset SHA1_FILE_DIRECTORY
|
||||
GIT_MERGE_VERBOSITY=5
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#include "cache.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
while (argc > 1) {
|
||||
puts(make_absolute_path(argv[1]));
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#include "cache.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc == 3 && !strcmp(argv[1], "normalize_absolute_path")) {
|
||||
char *buf = xmalloc(strlen(argv[2])+1);
|
||||
int rv = normalize_absolute_path(buf, argv[2]);
|
||||
assert(strlen(buf) == rv);
|
||||
puts(buf);
|
||||
}
|
||||
|
||||
if (argc >= 2 && !strcmp(argv[1], "make_absolute_path")) {
|
||||
while (argc > 2) {
|
||||
puts(make_absolute_path(argv[2]));
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
|
||||
int len = longest_ancestor_length(argv[2], argv[3]);
|
||||
printf("%d\n", len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Загрузка…
Ссылка в новой задаче