1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-20 12:16:07 +02:00

Merge branches 'jc/clone' and 'jc/name'

* jc/clone:
  git-clone: typofix.
  clone: record the remote primary branch with remotes/$origin/HEAD
  revamp git-clone (take #2).
  revamp git-clone.
  fetch,parse-remote,fmt-merge-msg: refs/remotes/* support

* jc/name:
  sha1_name: make core.warnambiguousrefs the default.
  sha1_name: warning ambiguous refs.
  get_sha1_basic(): try refs/... and finally refs/remotes/$foo/HEAD
  core.warnambiguousrefs: warns when "name" is used and both "name" branch and tag exists.
This commit is contained in:
Junio C Hamano 2006-03-26 00:22:53 -08:00
commit be1295d16a
20 changed files with 258 additions and 59 deletions

View File

@ -752,6 +752,7 @@ int main(int argc, const char **argv)
int found_rename;
const char* prefix = setup_git_directory();
git_config(git_default_config);
for(i = 1; i < argc; i++) {
if(options) {

View File

@ -165,6 +165,7 @@ extern void rollback_index_file(struct cache_file *);
extern int trust_executable_bit;
extern int assume_unchanged;
extern int only_use_symrefs;
extern int warn_ambiguous_refs;
extern int diff_rename_limit_default;
extern int shared_repository;
extern const char *apply_default_whitespace;

View File

@ -100,6 +100,7 @@ int main(int argc, char **argv)
int opt;
setup_git_directory();
git_config(git_default_config);
if (argc != 3 || get_sha1(argv[2], sha1))
usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");

View File

@ -232,6 +232,11 @@ int git_default_config(const char *var, const char *value)
return 0;
}
if (!strcmp(var, "core.warnambiguousrefs")) {
warn_ambiguous_refs = git_config_bool(var, value);
return 0;
}
if (!strcmp(var, "user.name")) {
strncpy(git_default_name, value, sizeof(git_default_name));
return 0;

View File

@ -14,6 +14,7 @@ char git_default_name[MAX_GITNAME];
int trust_executable_bit = 1;
int assume_unchanged = 0;
int only_use_symrefs = 0;
int warn_ambiguous_refs = 1;
int repository_format_version = 0;
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
int shared_repository = 0;

View File

@ -7,8 +7,9 @@
static int keep_pack;
static int quiet;
static int verbose;
static int fetch_all;
static const char fetch_pack_usage[] =
"git-fetch-pack [-q] [-v] [-k] [--thin] [--exec=upload-pack] [host:]directory <refs>...";
"git-fetch-pack [--all] [-q] [-v] [-k] [--thin] [--exec=upload-pack] [host:]directory <refs>...";
static const char *exec = "git-upload-pack";
#define COMPLETE (1U << 0)
@ -266,8 +267,9 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
for (prev = NULL, current = *refs; current; current = next) {
next = current->next;
if ((!memcmp(current->name, "refs/", 5) &&
check_ref_format(current->name + 5)) ||
!path_match(current->name, nr_match, match)) {
check_ref_format(current->name + 5)) ||
(!fetch_all &&
!path_match(current->name, nr_match, match))) {
if (prev == NULL)
*refs = next;
else
@ -376,7 +378,11 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
goto all_done;
}
if (find_common(fd, sha1, ref) < 0)
fprintf(stderr, "warning: no common commits\n");
if (!keep_pack)
/* When cloning, it is not unusual to have
* no common commit.
*/
fprintf(stderr, "warning: no common commits\n");
if (keep_pack)
status = receive_keep_pack(fd, "git-fetch-pack", quiet);
@ -426,6 +432,10 @@ int main(int argc, char **argv)
use_thin_pack = 1;
continue;
}
if (!strcmp("--all", arg)) {
fetch_all = 1;
continue;
}
if (!strcmp("-v", arg)) {
verbose = 1;
continue;

View File

@ -9,7 +9,7 @@
unset CDPATH
usage() {
echo >&2 "Usage: $0 [--bare] [-l [-s]] [-q] [-u <upload-pack>] [-o <name>] [-n] <repo> [<dir>]"
echo >&2 "Usage: $0 [--use-separate-remote] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [-o <name>] [-n] <repo> [<dir>]"
exit 1
}
@ -40,22 +40,73 @@ Perhaps git-update-server-info needs to be run there?"
do
name=`expr "$refname" : 'refs/\(.*\)'` &&
case "$name" in
*^*) ;;
*)
git-http-fetch -v -a -w "$name" "$name" "$1/" || exit 1
*^*) continue;;
esac
if test -n "$use_separate_remote" &&
branch_name=`expr "$name" : 'heads/\(.*\)'`
then
tname="remotes/$origin/$branch_name"
else
tname=$name
fi
git-http-fetch -v -a -w "$tname" "$name" "$1/" || exit 1
done <"$clone_tmp/refs"
rm -fr "$clone_tmp"
http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD"
}
# Read git-fetch-pack -k output and store the remote branches.
copy_refs='
use File::Path qw(mkpath);
use File::Basename qw(dirname);
my $git_dir = $ARGV[0];
my $use_separate_remote = $ARGV[1];
my $origin = $ARGV[2];
my $branch_top = ($use_separate_remote ? "remotes/$origin" : "heads");
my $tag_top = "tags";
sub store {
my ($sha1, $name, $top) = @_;
$name = "$git_dir/refs/$top/$name";
mkpath(dirname($name));
open O, ">", "$name";
print O "$sha1\n";
close O;
}
open FH, "<", "$git_dir/CLONE_HEAD";
while (<FH>) {
my ($sha1, $name) = /^([0-9a-f]{40})\s(.*)$/;
next if ($name =~ /\^\173/);
if ($name eq "HEAD") {
open O, ">", "$git_dir/REMOTE_HEAD";
print O "$sha1\n";
close O;
next;
}
if ($name =~ s/^refs\/heads\///) {
store($sha1, $name, $branch_top);
next;
}
if ($name =~ s/^refs\/tags\///) {
store($sha1, $name, $tag_top);
next;
}
}
close FH;
'
quiet=
use_local=no
local_shared=no
no_checkout=
upload_pack=
bare=
origin=origin
reference=
origin=
origin_override=
use_separate_remote=
while
case "$#,$1" in
0,*) break ;;
@ -68,9 +119,21 @@ while
*,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)
local_shared=yes; use_local=yes ;;
*,-q|*,--quiet) quiet=-q ;;
*,--use-separate-remote)
use_separate_remote=t ;;
1,-o) usage;;
1,--reference) usage ;;
*,--reference)
shift; reference="$1" ;;
*,--reference=*)
reference=`expr "$1" : '--reference=\(.*\)'` ;;
*,-o)
git-check-ref-format "$2" || {
case "$2" in
*/*)
echo >&2 "'$2' is not suitable for an origin name"
exit 1
esac
git-check-ref-format "heads/$2" || {
echo >&2 "'$2' is not suitable for a branch name"
exit 1
}
@ -100,9 +163,19 @@ then
echo >&2 '--bare and -o $origin options are incompatible.'
exit 1
fi
if test t = "$use_separate_remote"
then
echo >&2 '--bare and --use-separate-remote options are incompatible.'
exit 1
fi
no_checkout=yes
fi
if test -z "$origin"
then
origin=origin
fi
# Turn the source into an absolute path if
# it is local
repo="$1"
@ -130,6 +203,28 @@ yes)
GIT_DIR="$D/.git" ;;
esac
if test -n "$reference"
then
if test -d "$reference"
then
if test -d "$reference/.git/objects"
then
reference="$reference/.git"
fi
reference=$(cd "$reference" && pwd)
echo "$reference/objects" >"$GIT_DIR/objects/info/alternates"
(cd "$reference" && tar cf - refs) |
(cd "$GIT_DIR/refs" &&
mkdir reference-tmp &&
cd reference-tmp &&
tar xf -)
else
echo >&2 "$reference: not a local directory." && usage
fi
fi
rm -f "$GIT_DIR/CLONE_HEAD"
# We do local magic only when the user tells us to.
case "$local,$use_local" in
yes,yes)
@ -165,24 +260,14 @@ yes,yes)
} >"$GIT_DIR/objects/info/alternates"
;;
esac
# Make a duplicate of refs and HEAD pointer
HEAD=
if test -f "$repo/HEAD"
then
HEAD=HEAD
fi
(cd "$repo" && tar cf - refs $HEAD) |
(cd "$GIT_DIR" && tar xf -) || exit 1
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
;;
*)
case "$repo" in
rsync://*)
rsync $quiet -av --ignore-existing \
--exclude info "$repo/objects/" "$GIT_DIR/objects/" &&
rsync $quiet -av --ignore-existing \
--exclude info "$repo/refs/" "$GIT_DIR/refs/" || exit
--exclude info "$repo/objects/" "$GIT_DIR/objects/" ||
exit
# Look at objects/info/alternates for rsync -- http will
# support it natively and git native ones will do it on the
# remote end. Not having that file is not a crime.
@ -205,6 +290,7 @@ yes,yes)
done
rm -f "$GIT_DIR/TMP_ALT"
fi
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
;;
http://*)
if test -z "@@NO_CURL@@"
@ -217,38 +303,89 @@ yes,yes)
;;
*)
cd "$D" && case "$upload_pack" in
'') git-clone-pack $quiet "$repo" ;;
*) git-clone-pack $quiet "$upload_pack" "$repo" ;;
esac || {
echo >&2 "clone-pack from '$repo' failed."
'') git-fetch-pack --all -k $quiet "$repo" ;;
*) git-fetch-pack --all -k $quiet "$upload_pack" "$repo" ;;
esac >"$GIT_DIR/CLONE_HEAD" || {
echo >&2 "fetch-pack from '$repo' failed."
exit 1
}
;;
esac
;;
esac
test -d "$GIT_DIR/refs/reference-tmp" && rm -fr "$GIT_DIR/refs/reference-tmp"
if test -f "$GIT_DIR/CLONE_HEAD"
then
# Figure out where the remote HEAD points at.
perl -e "$copy_refs" "$GIT_DIR" "$use_separate_remote" "$origin"
fi
cd "$D" || exit
if test -f "$GIT_DIR/HEAD" && test -z "$bare"
if test -z "$bare" && test -f "$GIT_DIR/REMOTE_HEAD"
then
head_points_at=`git-symbolic-ref HEAD`
case "$head_points_at" in
refs/heads/*)
head_points_at=`expr "$head_points_at" : 'refs/heads/\(.*\)'`
mkdir -p "$GIT_DIR/remotes" &&
echo >"$GIT_DIR/remotes/origin" \
"URL: $repo
Pull: $head_points_at:$origin" &&
git-update-ref "refs/heads/$origin" $(git-rev-parse HEAD) &&
(cd "$GIT_DIR" && find "refs/heads" -type f -print) |
while read ref
head_sha1=`cat "$GIT_DIR/REMOTE_HEAD"`
# Figure out which remote branch HEAD points at.
case "$use_separate_remote" in
'') remote_top=refs/heads ;;
*) remote_top="refs/remotes/$origin" ;;
esac
# What to use to track the remote primary branch
if test -n "$use_separate_remote"
then
origin_tracking="remotes/$origin/master"
else
origin_tracking="heads/$origin"
fi
# The name under $remote_top the remote HEAD seems to point at
head_points_at=$(
(
echo "master"
cd "$GIT_DIR/$remote_top" &&
find . -type f -print | sed -e 's/^\.\///'
) | (
done=f
while read name
do
head=`expr "$ref" : 'refs/heads/\(.*\)'` &&
test "$head_points_at" = "$head" ||
test "$origin" = "$head" ||
echo "Pull: ${head}:${head}"
done >>"$GIT_DIR/remotes/origin"
test t = $done && continue
branch_tip=`cat "$GIT_DIR/$remote_top/$name"`
if test "$head_sha1" = "$branch_tip"
then
echo "$name"
done=t
fi
done
)
)
# Write out remotes/$origin file.
case "$head_points_at" in
?*)
mkdir -p "$GIT_DIR/remotes" &&
echo >"$GIT_DIR/remotes/$origin" \
"URL: $repo
Pull: refs/heads/$head_points_at:refs/$origin_tracking" &&
case "$use_separate_remote" in
t) git-update-ref HEAD "$head_sha1" ;;
*) git-update-ref "refs/heads/$origin" $(git-rev-parse HEAD) ;;
esac &&
(cd "$GIT_DIR/$remote_top" && find . -type f -print) |
while read dotslref
do
name=`expr "$dotslref" : './\(.*\)'` &&
test "$head_points_at" = "$name" ||
test "$origin" = "$name" ||
echo "Pull: refs/heads/${name}:$remote_top/${name}"
done >>"$GIT_DIR/remotes/$origin" &&
case "$use_separate_remote" in
t)
rm -f "refs/remotes/$origin/HEAD"
git-symbolic-ref "refs/remotes/$origin/HEAD" \
"refs/remotes/$origin/$head_points_at"
esac
esac
case "$no_checkout" in
@ -256,6 +393,7 @@ Pull: $head_points_at:$origin" &&
git-read-tree -m -u -v HEAD HEAD
esac
fi
rm -f "$GIT_DIR/CLONE_HEAD" "$GIT_DIR/REMOTE_HEAD"
trap - exit

View File

@ -94,6 +94,9 @@ append_fetch_head () {
# remote-nick is the URL given on the command line (or a shorthand)
# remote-name is the $GIT_DIR relative refs/ path we computed
# for this refspec.
# the $note_ variable will be fed to git-fmt-merge-msg for further
# processing.
case "$remote_name_" in
HEAD)
note_= ;;
@ -103,6 +106,9 @@ append_fetch_head () {
refs/tags/*)
note_="$(expr "$remote_name_" : 'refs/tags/\(.*\)')"
note_="tag '$note_' of " ;;
refs/remotes/*)
note_="$(expr "$remote_name_" : 'refs/remotes/\(.*\)')"
note_="remote branch '$note_' of " ;;
*)
note_="$remote_name of " ;;
esac
@ -147,10 +153,10 @@ fast_forward_local () {
else
echo >&2 "* $1: storing $3"
fi
git-update-ref "$1" "$2"
git-update-ref "$1" "$2"
;;
refs/heads/*)
refs/heads/* | refs/remotes/*)
# $1 is the ref being updated.
# $2 is the new value for the ref.
local=$(git-rev-parse --verify "$1^0" 2>/dev/null)

View File

@ -75,6 +75,7 @@ sub shortlog {
$src{$src} = {
BRANCH => [],
TAG => [],
R_BRANCH => [],
GENERIC => [],
# &1 == has HEAD.
# &2 == has others.
@ -91,6 +92,11 @@ sub shortlog {
push @{$src{$src}{TAG}}, $1;
$src{$src}{HEAD_STATUS} |= 2;
}
elsif (/^remote branch (.*)$/) {
$origin = $1;
push @{$src{$src}{R_BRANCH}}, $1;
$src{$src}{HEAD_STATUS} |= 2;
}
elsif (/^HEAD$/) {
$origin = $src;
$src{$src}{HEAD_STATUS} |= 1;
@ -123,6 +129,8 @@ sub shortlog {
}
push @this, andjoin("branch ", "branches ",
$src{$src}{BRANCH});
push @this, andjoin("remote branch ", "remote branches ",
$src{$src}{R_BRANCH});
push @this, andjoin("tag ", "tags ",
$src{$src}{TAG});
push @this, andjoin("commit ", "commits ",

View File

@ -86,14 +86,14 @@ canon_refs_list_for_fetch () {
local=$(expr "$ref" : '[^:]*:\(.*\)')
case "$remote" in
'') remote=HEAD ;;
refs/heads/* | refs/tags/*) ;;
heads/* | tags/* ) remote="refs/$remote" ;;
refs/heads/* | refs/tags/* | refs/remotes/*) ;;
heads/* | tags/* | remotes/* ) remote="refs/$remote" ;;
*) remote="refs/heads/$remote" ;;
esac
case "$local" in
'') local= ;;
refs/heads/* | refs/tags/*) ;;
heads/* | tags/* ) local="refs/$local" ;;
refs/heads/* | refs/tags/* | refs/remotes/*) ;;
heads/* | tags/* | remotes/* ) local="refs/$local" ;;
*) local="refs/heads/$local" ;;
esac

View File

@ -87,6 +87,7 @@ int main(int argc, const char **argv)
struct tree *tree;
prefix = setup_git_directory();
git_config(git_default_config);
if (prefix && *prefix)
chomp_prefix = strlen(prefix);
while (1 < argc && argv[1][0] == '-') {

View File

@ -237,6 +237,7 @@ int main(int argc, char **argv)
unsigned char rev1key[20], rev2key[20];
setup_git_directory();
git_config(git_default_config);
while (1 < argc && argv[1][0] == '-') {
char *arg = argv[1];

View File

@ -127,6 +127,7 @@ int main(int argc, char **argv)
int as_is = 0, all = 0, transform_stdin = 0;
setup_git_directory();
git_config(git_default_config);
if (argc < 2)
usage(name_rev_usage);

View File

@ -717,6 +717,7 @@ int main(int argc, char **argv)
merge_fn_t fn = NULL;
setup_git_directory();
git_config(git_default_config);
newfd = hold_index_file_for_update(&cache_file, get_index_file());
if (newfd < 0)

View File

@ -166,6 +166,8 @@ int main(int argc, char **argv)
unsigned char sha1[20];
const char *prefix = setup_git_directory();
git_config(git_default_config);
for (i = 1; i < argc; i++) {
struct stat st;
char *arg = argv[i];

View File

@ -362,6 +362,8 @@ int main(int argc, char **argv)
pid_t pid;
setup_git_directory();
git_config(git_default_config);
argv++;
for (i = 1; i < argc; i++, argv++) {
char *arg = *argv;

View File

@ -235,14 +235,21 @@ static int ambiguous_path(const char *path, int len)
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
{
static const char *prefix[] = {
"",
"refs",
"refs/tags",
"refs/heads",
static const char *fmt[] = {
"%.*s",
"refs/%.*s",
"refs/tags/%.*s",
"refs/heads/%.*s",
"refs/remotes/%.*s",
"refs/remotes/%.*s/HEAD",
NULL
};
const char **p;
const char *warning = "warning: refname '%.*s' is ambiguous.\n";
char *pathname;
int already_found = 0;
unsigned char *this_result;
unsigned char sha1_from_ref[20];
if (len == 40 && !get_sha1_hex(str, sha1))
return 0;
@ -251,11 +258,21 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
if (ambiguous_path(str, len))
return -1;
for (p = prefix; *p; p++) {
char *pathname = git_path("%s/%.*s", *p, len, str);
if (!read_ref(pathname, sha1))
return 0;
for (p = fmt; *p; p++) {
this_result = already_found ? sha1_from_ref : sha1;
pathname = git_path(*p, len, str);
if (!read_ref(pathname, this_result)) {
if (warn_ambiguous_refs) {
if (already_found)
fprintf(stderr, warning, len, str);
already_found++;
}
else
return 0;
}
}
if (already_found)
return 0;
return -1;
}

View File

@ -380,6 +380,7 @@ int main(int argc, char **argv)
struct tree_desc tree;
setup_git_directory();
git_config(git_default_config);
switch (argc) {
case 3:

View File

@ -30,6 +30,7 @@ int main(int argc, char **argv)
usage("git-unpack-file <sha1>");
setup_git_directory();
git_config(git_default_config);
puts(create_temp_file(sha1));
return 0;

View File

@ -25,6 +25,7 @@ int main(int argc, char **argv)
int fd, written;
setup_git_directory();
git_config(git_default_config);
if (argc < 3 || argc > 4)
usage(git_update_ref_usage);