Merge branch 'maint'
* maint: Document accumulated fixes since 1.7.9.2 Git 1.7.8.5 grep -P: Fix matching ^ and $ am: don't infloop for an empty input file rebase -m: only call "notes copy" when rewritten exists and is non-empty git-p4: remove bash-ism in t9800 git-p4: remove bash-ism in t9809 git-p4: fix submit regression with clientSpec and subdir clone git-p4: set useClientSpec variable on initial clone Makefile: add thread-utils.h to LIB_H Conflicts: RelNotes t/t9809-git-p4-client-view.sh
This commit is contained in:
commit
8080906245
@ -87,15 +87,6 @@ Unless otherwise noted, all the fixes since v1.7.9 in the maintenance
|
||||
releases are contained in this release (see release notes to them for
|
||||
details).
|
||||
|
||||
* The config.mak.autogen generated by optional autoconf support tried
|
||||
to link the binary with -lintl even when libintl.h is missing from
|
||||
the system.
|
||||
(merge a8356d4 js/configure-libintl later to maint).
|
||||
|
||||
* "git add --refresh <pathspec>" used to warn about unmerged paths
|
||||
outside the given pathspec.
|
||||
(merge 3d1f148 jc/add-refresh-unmerged later to maint).
|
||||
|
||||
* "gitweb" used to drop warnings in the log file when "heads" view is
|
||||
accessed in a repository whose HEAD does not point at a valid
|
||||
branch.
|
||||
|
19
Documentation/RelNotes/1.7.8.5.txt
Normal file
19
Documentation/RelNotes/1.7.8.5.txt
Normal file
@ -0,0 +1,19 @@
|
||||
Git v1.7.8.5 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.7.8.4
|
||||
--------------------
|
||||
|
||||
* Dependency on our thread-utils.h header file was missing for
|
||||
objects that depend on it in the Makefile.
|
||||
|
||||
* "git am" when fed an empty file did not correctly finish reading it
|
||||
when it attempts to guess the input format.
|
||||
|
||||
* "git grep -P" (when PCRE is enabled in the build) did not match the
|
||||
beginning and the end of the line correctly with ^ and $.
|
||||
|
||||
* "git rebase -m" tried to run "git notes copy" needlessly when
|
||||
nothing was rewritten.
|
||||
|
||||
Also contains minor fixes and documentation updates.
|
17
Documentation/RelNotes/1.7.9.3.txt
Normal file
17
Documentation/RelNotes/1.7.9.3.txt
Normal file
@ -0,0 +1,17 @@
|
||||
Git v1.7.9.3 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.7.9.2
|
||||
--------------------
|
||||
|
||||
* "git p4" (in contrib/) submit the changes to a wrong place when the
|
||||
"--use-client-spec" option is set.
|
||||
|
||||
* The config.mak.autogen generated by optional autoconf support tried
|
||||
to link the binary with -lintl even when libintl.h is missing from
|
||||
the system.
|
||||
|
||||
* "git add --refresh <pathspec>" used to warn about unmerged paths
|
||||
outside the given pathspec.
|
||||
|
||||
Also contains minor fixes and documentation updates.
|
@ -303,9 +303,13 @@ CLIENT SPEC
|
||||
-----------
|
||||
The p4 client specification is maintained with the 'p4 client' command
|
||||
and contains among other fields, a View that specifies how the depot
|
||||
is mapped into the client repository. Git-p4 can consult the client
|
||||
spec when given the '--use-client-spec' option or useClientSpec
|
||||
variable.
|
||||
is mapped into the client repository. The 'clone' and 'sync' commands
|
||||
can consult the client spec when given the '--use-client-spec' option or
|
||||
when the useClientSpec variable is true. After 'git p4 clone', the
|
||||
useClientSpec variable is automatically set in the repository
|
||||
configuration file. This allows future 'git p4 submit' commands to
|
||||
work properly; the submit command looks only at the variable and does
|
||||
not have a command-line option.
|
||||
|
||||
The full syntax for a p4 view is documented in 'p4 help views'. Git-p4
|
||||
knows only a subset of the view syntax. It understands multi-line
|
||||
|
1
Makefile
1
Makefile
@ -620,6 +620,7 @@ LIB_H += streaming.h
|
||||
LIB_H += string-list.h
|
||||
LIB_H += submodule.h
|
||||
LIB_H += tag.h
|
||||
LIB_H += thread-utils.h
|
||||
LIB_H += transport.h
|
||||
LIB_H += tree.h
|
||||
LIB_H += tree-walk.h
|
||||
|
@ -596,6 +596,46 @@ def p4PathStartsWith(path, prefix):
|
||||
return path.lower().startswith(prefix.lower())
|
||||
return path.startswith(prefix)
|
||||
|
||||
def getClientSpec():
|
||||
"""Look at the p4 client spec, create a View() object that contains
|
||||
all the mappings, and return it."""
|
||||
|
||||
specList = p4CmdList("client -o")
|
||||
if len(specList) != 1:
|
||||
die('Output from "client -o" is %d lines, expecting 1' %
|
||||
len(specList))
|
||||
|
||||
# dictionary of all client parameters
|
||||
entry = specList[0]
|
||||
|
||||
# just the keys that start with "View"
|
||||
view_keys = [ k for k in entry.keys() if k.startswith("View") ]
|
||||
|
||||
# hold this new View
|
||||
view = View()
|
||||
|
||||
# append the lines, in order, to the view
|
||||
for view_num in range(len(view_keys)):
|
||||
k = "View%d" % view_num
|
||||
if k not in view_keys:
|
||||
die("Expected view key %s missing" % k)
|
||||
view.append(entry[k])
|
||||
|
||||
return view
|
||||
|
||||
def getClientRoot():
|
||||
"""Grab the client directory."""
|
||||
|
||||
output = p4CmdList("client -o")
|
||||
if len(output) != 1:
|
||||
die('Output from "client -o" is %d lines, expecting 1' % len(output))
|
||||
|
||||
entry = output[0]
|
||||
if "Root" not in entry:
|
||||
die('Client has no "Root"')
|
||||
|
||||
return entry["Root"]
|
||||
|
||||
class Command:
|
||||
def __init__(self):
|
||||
self.usage = "usage: %prog [options]"
|
||||
@ -1220,11 +1260,20 @@ class P4Submit(Command, P4UserMap):
|
||||
print "Internal error: cannot locate perforce depot path from existing branches"
|
||||
sys.exit(128)
|
||||
|
||||
self.clientPath = p4Where(self.depotPath)
|
||||
self.useClientSpec = False
|
||||
if gitConfig("git-p4.useclientspec", "--bool") == "true":
|
||||
self.useClientSpec = True
|
||||
if self.useClientSpec:
|
||||
self.clientSpecDirs = getClientSpec()
|
||||
|
||||
if len(self.clientPath) == 0:
|
||||
print "Error: Cannot locate perforce checkout of %s in client view" % self.depotPath
|
||||
sys.exit(128)
|
||||
if self.useClientSpec:
|
||||
# all files are relative to the client spec
|
||||
self.clientPath = getClientRoot()
|
||||
else:
|
||||
self.clientPath = p4Where(self.depotPath)
|
||||
|
||||
if self.clientPath == "":
|
||||
die("Error: Cannot locate perforce checkout of %s in client view" % self.depotPath)
|
||||
|
||||
print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath)
|
||||
self.oldWorkingDirectory = os.getcwd()
|
||||
@ -1530,6 +1579,7 @@ class P4Sync(Command, P4UserMap):
|
||||
self.p4BranchesInGit = []
|
||||
self.cloneExclude = []
|
||||
self.useClientSpec = False
|
||||
self.useClientSpec_from_options = False
|
||||
self.clientSpecDirs = None
|
||||
self.tempBranches = []
|
||||
self.tempBranchLocation = "git-p4-tmp"
|
||||
@ -2223,33 +2273,6 @@ class P4Sync(Command, P4UserMap):
|
||||
print self.gitError.read()
|
||||
|
||||
|
||||
def getClientSpec(self):
|
||||
specList = p4CmdList("client -o")
|
||||
if len(specList) != 1:
|
||||
die('Output from "client -o" is %d lines, expecting 1' %
|
||||
len(specList))
|
||||
|
||||
# dictionary of all client parameters
|
||||
entry = specList[0]
|
||||
|
||||
# just the keys that start with "View"
|
||||
view_keys = [ k for k in entry.keys() if k.startswith("View") ]
|
||||
|
||||
# hold this new View
|
||||
view = View()
|
||||
|
||||
# append the lines, in order, to the view
|
||||
for view_num in range(len(view_keys)):
|
||||
k = "View%d" % view_num
|
||||
if k not in view_keys:
|
||||
die("Expected view key %s missing" % k)
|
||||
view.append(entry[k])
|
||||
|
||||
self.clientSpecDirs = view
|
||||
if self.verbose:
|
||||
for i, m in enumerate(self.clientSpecDirs.mappings):
|
||||
print "clientSpecDirs %d: %s" % (i, str(m))
|
||||
|
||||
def run(self, args):
|
||||
self.depotPaths = []
|
||||
self.changeRange = ""
|
||||
@ -2282,11 +2305,15 @@ class P4Sync(Command, P4UserMap):
|
||||
if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch):
|
||||
system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch))
|
||||
|
||||
if not self.useClientSpec:
|
||||
# accept either the command-line option, or the configuration variable
|
||||
if self.useClientSpec:
|
||||
# will use this after clone to set the variable
|
||||
self.useClientSpec_from_options = True
|
||||
else:
|
||||
if gitConfig("git-p4.useclientspec", "--bool") == "true":
|
||||
self.useClientSpec = True
|
||||
if self.useClientSpec:
|
||||
self.getClientSpec()
|
||||
self.clientSpecDirs = getClientSpec()
|
||||
|
||||
# TODO: should always look at previous commits,
|
||||
# merge with previous imports, if possible.
|
||||
@ -2607,6 +2634,10 @@ class P4Clone(P4Sync):
|
||||
else:
|
||||
print "Could not detect main branch. No checkout/master branch created."
|
||||
|
||||
# auto-set this variable if invoked with --use-client-spec
|
||||
if self.useClientSpec_from_options:
|
||||
system("git config --bool git-p4.useclientspec true")
|
||||
|
||||
return True
|
||||
|
||||
class P4Branches(Command):
|
||||
|
@ -202,7 +202,7 @@ check_patch_format () {
|
||||
l1=
|
||||
while test -z "$l1"
|
||||
do
|
||||
read l1
|
||||
read l1 || break
|
||||
done
|
||||
read l2
|
||||
read l3
|
||||
|
@ -90,10 +90,13 @@ call_merge () {
|
||||
|
||||
finish_rb_merge () {
|
||||
move_to_original_branch
|
||||
git notes copy --for-rewrite=rebase < "$state_dir"/rewritten
|
||||
if test -x "$GIT_DIR"/hooks/post-rewrite &&
|
||||
test -s "$state_dir"/rewritten; then
|
||||
"$GIT_DIR"/hooks/post-rewrite rebase < "$state_dir"/rewritten
|
||||
if test -s "$state_dir"/rewritten
|
||||
then
|
||||
git notes copy --for-rewrite=rebase <"$state_dir"/rewritten
|
||||
if test -x "$GIT_DIR"/hooks/post-rewrite
|
||||
then
|
||||
"$GIT_DIR"/hooks/post-rewrite rebase <"$state_dir"/rewritten
|
||||
fi
|
||||
fi
|
||||
rm -r "$state_dir"
|
||||
say All done.
|
||||
|
2
grep.c
2
grep.c
@ -79,7 +79,7 @@ static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
|
||||
{
|
||||
const char *error;
|
||||
int erroffset;
|
||||
int options = 0;
|
||||
int options = PCRE_MULTILINE;
|
||||
|
||||
if (opt->ignore_case)
|
||||
options |= PCRE_CASELESS;
|
||||
|
@ -505,4 +505,14 @@ test_expect_success 'am -q is quiet' '
|
||||
! test -s output.out
|
||||
'
|
||||
|
||||
test_expect_success 'am empty-file does not infloop' '
|
||||
rm -fr .git/rebase-apply &&
|
||||
git reset --hard &&
|
||||
touch empty-file &&
|
||||
test_tick &&
|
||||
{ git am empty-file > actual 2>&1 && false || :; } &&
|
||||
echo Patch format detection failed. >expected &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -234,8 +234,10 @@ test_expect_success 'refuse to preserve users without perms' '
|
||||
git config git-p4.skipSubmitEditCheck true &&
|
||||
echo "username-noperms: a change by alice" >>file1 &&
|
||||
git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
|
||||
P4EDITOR=touch P4USER=bob P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user &&
|
||||
test_must_fail git diff --exit-code HEAD..p4/master
|
||||
P4EDITOR=touch P4USER=bob P4PASSWD=secret &&
|
||||
export P4EDITOR P4USER P4PASSWD &&
|
||||
test_must_fail "$GITP4" commit --preserve-user &&
|
||||
! git diff --exit-code HEAD..p4/master
|
||||
)
|
||||
'
|
||||
|
||||
@ -250,13 +252,15 @@ test_expect_success 'preserve user where author is unknown to p4' '
|
||||
git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 &&
|
||||
echo "username-unknown: a change by charlie" >>file1 &&
|
||||
git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 &&
|
||||
P4EDITOR=touch P4USER=alice P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user &&
|
||||
test_must_fail git diff --exit-code HEAD..p4/master &&
|
||||
P4EDITOR=touch P4USER=alice P4PASSWD=secret &&
|
||||
export P4EDITOR P4USER P4PASSWD &&
|
||||
test_must_fail "$GITP4" commit --preserve-user &&
|
||||
! git diff --exit-code HEAD..p4/master &&
|
||||
|
||||
echo "$0: repeat with allowMissingP4Users enabled" &&
|
||||
git config git-p4.allowMissingP4Users true &&
|
||||
git config git-p4.preserveUser true &&
|
||||
P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit &&
|
||||
"$GITP4" commit &&
|
||||
git diff --exit-code HEAD..p4/master &&
|
||||
p4_check_commit_author file1 alice
|
||||
)
|
||||
@ -275,20 +279,22 @@ test_expect_success 'not preserving user with mixed authorship' '
|
||||
p4_add_user derek Derek &&
|
||||
|
||||
make_change_by_user usernamefile3 Derek derek@localhost &&
|
||||
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\
|
||||
P4EDITOR=cat P4USER=alice P4PASSWD=secret &&
|
||||
export P4EDITOR P4USER P4PASSWD &&
|
||||
"$GITP4" commit |\
|
||||
grep "git author derek@localhost does not match" &&
|
||||
|
||||
make_change_by_user usernamefile3 Charlie charlie@localhost &&
|
||||
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\
|
||||
"$GITP4" commit |\
|
||||
grep "git author charlie@localhost does not match" &&
|
||||
|
||||
make_change_by_user usernamefile3 alice alice@localhost &&
|
||||
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" |\
|
||||
"$GITP4" commit |\
|
||||
test_must_fail grep "git author.*does not match" &&
|
||||
|
||||
git config git-p4.skipUserNameCheck true &&
|
||||
make_change_by_user usernamefile3 Charlie charlie@localhost &&
|
||||
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\
|
||||
"$GITP4" commit |\
|
||||
test_must_fail grep "git author.*does not match" &&
|
||||
|
||||
p4_check_commit_author usernamefile3 alice
|
||||
|
@ -31,7 +31,7 @@ client_view() {
|
||||
#
|
||||
check_files_exist() {
|
||||
ok=0 &&
|
||||
num=${#@} &&
|
||||
num=$# &&
|
||||
for arg ; do
|
||||
test_path_is_file "$arg" &&
|
||||
ok=$(($ok + 1))
|
||||
@ -71,20 +71,24 @@ git_verify() {
|
||||
# - dir2
|
||||
# - file21
|
||||
# - file22
|
||||
init_depot() {
|
||||
for d in 1 2 ; do
|
||||
mkdir -p dir$d &&
|
||||
for f in 1 2 ; do
|
||||
echo dir$d/file$d$f >dir$d/file$d$f &&
|
||||
p4 add dir$d/file$d$f &&
|
||||
p4 submit -d "dir$d/file$d$f"
|
||||
done
|
||||
done &&
|
||||
find . -type f ! -name files >files &&
|
||||
check_files_exist dir1/file11 dir1/file12 \
|
||||
dir2/file21 dir2/file22
|
||||
}
|
||||
|
||||
test_expect_success 'init depot' '
|
||||
(
|
||||
cd "$cli" &&
|
||||
for d in 1 2 ; do
|
||||
mkdir -p dir$d &&
|
||||
for f in 1 2 ; do
|
||||
echo dir$d/file$d$f >dir$d/file$d$f &&
|
||||
p4 add dir$d/file$d$f &&
|
||||
p4 submit -d "dir$d/file$d$f"
|
||||
done
|
||||
done &&
|
||||
find . -type f ! -name files >files &&
|
||||
check_files_exist dir1/file11 dir1/file12 \
|
||||
dir2/file21 dir2/file22
|
||||
init_depot
|
||||
)
|
||||
'
|
||||
|
||||
@ -246,6 +250,139 @@ test_expect_success 'quotes on rhs only' '
|
||||
git_verify "cdir 1/file11" "cdir 1/file12"
|
||||
'
|
||||
|
||||
#
|
||||
# Submit tests
|
||||
#
|
||||
|
||||
# clone sets variable
|
||||
test_expect_success 'clone --use-client-spec sets useClientSpec' '
|
||||
client_view "//depot/... //client/..." &&
|
||||
test_when_finished cleanup_git &&
|
||||
"$GITP4" clone --use-client-spec --dest="$git" //depot &&
|
||||
(
|
||||
cd "$git" &&
|
||||
git config --bool git-p4.useClientSpec >actual &&
|
||||
echo true >true &&
|
||||
test_cmp actual true
|
||||
)
|
||||
'
|
||||
|
||||
# clone just a subdir of the client spec
|
||||
test_expect_success 'subdir clone' '
|
||||
client_view "//depot/... //client/..." &&
|
||||
files="dir1/file11 dir1/file12 dir2/file21 dir2/file22" &&
|
||||
client_verify $files &&
|
||||
test_when_finished cleanup_git &&
|
||||
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
|
||||
git_verify dir1/file11 dir1/file12
|
||||
'
|
||||
|
||||
#
|
||||
# submit back, see what happens: five cases
|
||||
#
|
||||
test_expect_success 'subdir clone, submit modify' '
|
||||
client_view "//depot/... //client/..." &&
|
||||
test_when_finished cleanup_git &&
|
||||
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
|
||||
(
|
||||
cd "$git" &&
|
||||
git config git-p4.skipSubmitEdit true &&
|
||||
echo line >>dir1/file12 &&
|
||||
git add dir1/file12 &&
|
||||
git commit -m dir1/file12 &&
|
||||
"$GITP4" submit
|
||||
) &&
|
||||
(
|
||||
cd "$cli" &&
|
||||
test_path_is_file dir1/file12 &&
|
||||
test_line_count = 2 dir1/file12
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'subdir clone, submit add' '
|
||||
client_view "//depot/... //client/..." &&
|
||||
test_when_finished cleanup_git &&
|
||||
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
|
||||
(
|
||||
cd "$git" &&
|
||||
git config git-p4.skipSubmitEdit true &&
|
||||
echo file13 >dir1/file13 &&
|
||||
git add dir1/file13 &&
|
||||
git commit -m dir1/file13 &&
|
||||
"$GITP4" submit
|
||||
) &&
|
||||
(
|
||||
cd "$cli" &&
|
||||
test_path_is_file dir1/file13
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'subdir clone, submit delete' '
|
||||
client_view "//depot/... //client/..." &&
|
||||
test_when_finished cleanup_git &&
|
||||
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
|
||||
(
|
||||
cd "$git" &&
|
||||
git config git-p4.skipSubmitEdit true &&
|
||||
git rm dir1/file12 &&
|
||||
git commit -m "delete dir1/file12" &&
|
||||
"$GITP4" submit
|
||||
) &&
|
||||
(
|
||||
cd "$cli" &&
|
||||
test_path_is_missing dir1/file12
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'subdir clone, submit copy' '
|
||||
client_view "//depot/... //client/..." &&
|
||||
test_when_finished cleanup_git &&
|
||||
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
|
||||
(
|
||||
cd "$git" &&
|
||||
git config git-p4.skipSubmitEdit true &&
|
||||
git config git-p4.detectCopies true &&
|
||||
cp dir1/file11 dir1/file11a &&
|
||||
git add dir1/file11a &&
|
||||
git commit -m "copy to dir1/file11a" &&
|
||||
"$GITP4" submit
|
||||
) &&
|
||||
(
|
||||
cd "$cli" &&
|
||||
test_path_is_file dir1/file11a
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'subdir clone, submit rename' '
|
||||
client_view "//depot/... //client/..." &&
|
||||
test_when_finished cleanup_git &&
|
||||
"$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
|
||||
(
|
||||
cd "$git" &&
|
||||
git config git-p4.skipSubmitEdit true &&
|
||||
git config git-p4.detectRenames true &&
|
||||
git mv dir1/file13 dir1/file13a &&
|
||||
git commit -m "rename dir1/file13 to dir1/file13a" &&
|
||||
"$GITP4" submit
|
||||
) &&
|
||||
(
|
||||
cd "$cli" &&
|
||||
test_path_is_missing dir1/file13 &&
|
||||
test_path_is_file dir1/file13a
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'reinit depot' '
|
||||
(
|
||||
cd "$cli" &&
|
||||
p4 sync -f &&
|
||||
rm files &&
|
||||
p4 delete */* &&
|
||||
p4 submit -d "delete all files" &&
|
||||
init_depot
|
||||
)
|
||||
'
|
||||
|
||||
#
|
||||
# What happens when two files of the same name are overlayed together?
|
||||
# The last-listed file should take preference.
|
||||
|
Loading…
Reference in New Issue
Block a user