@@ -464,71 +464,47 @@ class P4Submit(Command):
464
464
def __init__ (self ):
465
465
Command .__init__ (self )
466
466
self .options = [
467
- optparse .make_option ("--continue" , action = "store_false" , dest = "firstTime" ),
468
467
optparse .make_option ("--verbose" , dest = "verbose" , action = "store_true" ),
469
468
optparse .make_option ("--origin" , dest = "origin" ),
470
- optparse .make_option ("--reset" , action = "store_true" , dest = "reset" ),
471
- optparse .make_option ("--log-substitutions" , dest = "substFile" ),
472
- optparse .make_option ("--direct" , dest = "directSubmit" , action = "store_true" ),
473
469
optparse .make_option ("-M" , dest = "detectRename" , action = "store_true" ),
474
470
]
475
471
self .description = "Submit changes from git to the perforce depot."
476
472
self .usage += " [name of git branch to submit into perforce depot]"
477
- self .firstTime = True
478
- self .reset = False
479
473
self .interactive = True
480
- self .substFile = ""
481
- self .firstTime = True
482
474
self .origin = ""
483
- self .directSubmit = False
484
475
self .detectRename = False
485
476
self .verbose = False
486
477
self .isWindows = (platform .system () == "Windows" )
487
478
488
- self .logSubstitutions = {}
489
- self .logSubstitutions ["<enter description here>" ] = "%log%"
490
- self .logSubstitutions ["\t Details:" ] = "\t Details: %log%"
491
-
492
479
def check (self ):
493
480
if len (p4CmdList ("opened ..." )) > 0 :
494
481
die ("You have files opened with perforce! Close them before starting the sync." )
495
482
496
- def start (self ):
497
- if len (self .config ) > 0 and not self .reset :
498
- die ("Cannot start sync. Previous sync config found at %s\n "
499
- "If you want to start submitting again from scratch "
500
- "maybe you want to call git-p4 submit --reset" % self .configFile )
501
-
502
- commits = []
503
- if self .directSubmit :
504
- commits .append ("0" )
505
- else :
506
- for line in read_pipe_lines ("git rev-list --no-merges %s..%s" % (self .origin , self .master )):
507
- commits .append (line .strip ())
508
- commits .reverse ()
509
-
510
- self .config ["commits" ] = commits
511
-
483
+ # replaces everything between 'Description:' and the next P4 submit template field with the
484
+ # commit message
512
485
def prepareLogMessage (self , template , message ):
513
486
result = ""
514
487
488
+ inDescriptionSection = False
489
+
515
490
for line in template .split ("\n " ):
516
491
if line .startswith ("#" ):
517
492
result += line + "\n "
518
493
continue
519
494
520
- substituted = False
521
- for key in self .logSubstitutions .keys ():
522
- if line .find (key ) != - 1 :
523
- value = self .logSubstitutions [key ]
524
- value = value .replace ("%log%" , message )
525
- if value != "@remove@" :
526
- result += line .replace (key , value ) + "\n "
527
- substituted = True
528
- break
495
+ if inDescriptionSection :
496
+ if line .startswith ("Files:" ):
497
+ inDescriptionSection = False
498
+ else :
499
+ continue
500
+ else :
501
+ if line .startswith ("Description:" ):
502
+ inDescriptionSection = True
503
+ line += "\n "
504
+ for messageLine in message .split ("\n " ):
505
+ line += "\t " + messageLine + "\n "
529
506
530
- if not substituted :
531
- result += line + "\n "
507
+ result += line + "\n "
532
508
533
509
return result
534
510
@@ -557,13 +533,9 @@ class P4Submit(Command):
557
533
return template
558
534
559
535
def applyCommit (self , id ):
560
- if self .directSubmit :
561
- print "Applying local change in working directory/index"
562
- diff = self .diffStatus
563
- else :
564
- print "Applying %s" % (read_pipe ("git log --max-count=1 --pretty=oneline %s" % id ))
565
- diffOpts = ("" , "-M" )[self .detectRename ]
566
- diff = read_pipe_lines ("git diff-tree -r %s \" %s^\" \" %s\" " % (diffOpts , id , id ))
536
+ print "Applying %s" % (read_pipe ("git log --max-count=1 --pretty=oneline %s" % id ))
537
+ diffOpts = ("" , "-M" )[self .detectRename ]
538
+ diff = read_pipe_lines ("git diff-tree -r %s \" %s^\" \" %s\" " % (diffOpts , id , id ))
567
539
filesToAdd = set ()
568
540
filesToDelete = set ()
569
541
editedFiles = set ()
@@ -598,10 +570,7 @@ class P4Submit(Command):
598
570
else :
599
571
die ("unknown modifier %s for %s" % (modifier , path ))
600
572
601
- if self .directSubmit :
602
- diffcmd = "cat \" %s\" " % self .diffFile
603
- else :
604
- diffcmd = "git format-patch -k --stdout \" %s^\" ..\" %s\" " % (id , id )
573
+ diffcmd = "git format-patch -k --stdout \" %s^\" ..\" %s\" " % (id , id )
605
574
patchcmd = diffcmd + " | git apply "
606
575
tryPatchCmd = patchcmd + "--check -"
607
576
applyPatchCmd = patchcmd + "--check --apply -"
@@ -649,13 +618,10 @@ class P4Submit(Command):
649
618
mode = filesToChangeExecBit [f ]
650
619
setP4ExecBit (f , mode )
651
620
652
- logMessage = ""
653
- if not self .directSubmit :
654
- logMessage = extractLogMessageFromGitCommit (id )
655
- logMessage = logMessage .replace ("\n " , "\n \t " )
656
- if self .isWindows :
657
- logMessage = logMessage .replace ("\n " , "\r \n " )
658
- logMessage = logMessage .strip ()
621
+ logMessage = extractLogMessageFromGitCommit (id )
622
+ if self .isWindows :
623
+ logMessage = logMessage .replace ("\n " , "\r \n " )
624
+ logMessage = logMessage .strip ()
659
625
660
626
template = self .prepareSubmitTemplate ()
661
627
@@ -694,12 +660,6 @@ class P4Submit(Command):
694
660
if self .isWindows :
695
661
submitTemplate = submitTemplate .replace ("\r \n " , "\n " )
696
662
697
- if self .directSubmit :
698
- print "Submitting to git first"
699
- os .chdir (self .oldWorkingDirectory )
700
- write_pipe ("git commit -a -F -" , submitTemplate )
701
- os .chdir (self .clientPath )
702
-
703
663
write_pipe ("p4 submit -i" , submitTemplate )
704
664
else :
705
665
fileName = "submit.txt"
@@ -741,65 +701,33 @@ class P4Submit(Command):
741
701
print "Perforce checkout for depot path %s located at %s" % (self .depotPath , self .clientPath )
742
702
self .oldWorkingDirectory = os .getcwd ()
743
703
744
- if self .directSubmit :
745
- self .diffStatus = read_pipe_lines ("git diff -r --name-status HEAD" )
746
- if len (self .diffStatus ) == 0 :
747
- print "No changes in working directory to submit."
748
- return True
749
- patch = read_pipe ("git diff -p --binary --diff-filter=ACMRTUXB HEAD" )
750
- self .diffFile = self .gitdir + "/p4-git-diff"
751
- f = open (self .diffFile , "wb" )
752
- f .write (patch )
753
- f .close ();
754
-
755
704
os .chdir (self .clientPath )
756
705
print "Syncronizing p4 checkout..."
757
706
system ("p4 sync ..." )
758
707
759
- if self .reset :
760
- self .firstTime = True
761
-
762
- if len (self .substFile ) > 0 :
763
- for line in open (self .substFile , "r" ).readlines ():
764
- tokens = line .strip ().split ("=" )
765
- self .logSubstitutions [tokens [0 ]] = tokens [1 ]
766
-
767
708
self .check ()
768
- self .configFile = self .gitdir + "/p4-git-sync.cfg"
769
- self .config = shelve .open (self .configFile , writeback = True )
770
-
771
- if self .firstTime :
772
- self .start ()
773
709
774
- commits = self .config .get ("commits" , [])
710
+ commits = []
711
+ for line in read_pipe_lines ("git rev-list --no-merges %s..%s" % (self .origin , self .master )):
712
+ commits .append (line .strip ())
713
+ commits .reverse ()
775
714
776
715
while len (commits ) > 0 :
777
- self .firstTime = False
778
716
commit = commits [0 ]
779
717
commits = commits [1 :]
780
- self .config ["commits" ] = commits
781
718
self .applyCommit (commit )
782
719
if not self .interactive :
783
720
break
784
721
785
- self .config .close ()
786
-
787
- if self .directSubmit :
788
- os .remove (self .diffFile )
789
-
790
722
if len (commits ) == 0 :
791
- if self .firstTime :
792
- print "No changes found to apply between %s and current HEAD" % self .origin
793
- else :
794
- print "All changes applied!"
795
- os .chdir (self .oldWorkingDirectory )
723
+ print "All changes applied!"
724
+ os .chdir (self .oldWorkingDirectory )
796
725
797
- sync = P4Sync ()
798
- sync .run ([])
726
+ sync = P4Sync ()
727
+ sync .run ([])
799
728
800
- rebase = P4Rebase ()
801
- rebase .rebase ()
802
- os .remove (self .configFile )
729
+ rebase = P4Rebase ()
730
+ rebase .rebase ()
803
731
804
732
return True
805
733
@@ -817,7 +745,9 @@ class P4Sync(Command):
817
745
help = "Import into refs/heads/ , not refs/remotes" ),
818
746
optparse .make_option ("--max-changes" , dest = "maxChanges" ),
819
747
optparse .make_option ("--keep-path" , dest = "keepRepoPath" , action = 'store_true' ,
820
- help = "Keep entire BRANCH/DIR/SUBDIR prefix during import" )
748
+ help = "Keep entire BRANCH/DIR/SUBDIR prefix during import" ),
749
+ optparse .make_option ("--use-client-spec" , dest = "useClientSpec" , action = 'store_true' ,
750
+ help = "Only sync files that are included in the Perforce Client Spec" )
821
751
]
822
752
self .description = """Imports from Perforce into a git repository.\n
823
753
example:
@@ -843,18 +773,27 @@ class P4Sync(Command):
843
773
self .keepRepoPath = False
844
774
self .depotPaths = None
845
775
self .p4BranchesInGit = []
776
+ self .cloneExclude = []
777
+ self .useClientSpec = False
778
+ self .clientSpecDirs = []
846
779
847
780
if gitConfig ("git-p4.syncFromOrigin" ) == "false" :
848
781
self .syncWithOrigin = False
849
782
850
783
def extractFilesFromCommit (self , commit ):
784
+ self .cloneExclude = [re .sub (r"\.\.\.$" , "" , path )
785
+ for path in self .cloneExclude ]
851
786
files = []
852
787
fnum = 0
853
788
while commit .has_key ("depotFile%s" % fnum ):
854
789
path = commit ["depotFile%s" % fnum ]
855
790
856
- found = [p for p in self .depotPaths
857
- if path .startswith (p )]
791
+ if [p for p in self .cloneExclude
792
+ if path .startswith (p )]:
793
+ found = False
794
+ else :
795
+ found = [p for p in self .depotPaths
796
+ if path .startswith (p )]
858
797
if not found :
859
798
fnum = fnum + 1
860
799
continue
@@ -911,11 +850,21 @@ class P4Sync(Command):
911
850
912
851
## Should move this out, doesn't use SELF.
913
852
def readP4Files (self , files ):
853
+ for f in files :
854
+ for val in self .clientSpecDirs :
855
+ if f ['path' ].startswith (val [0 ]):
856
+ if val [1 ] > 0 :
857
+ f ['include' ] = True
858
+ else :
859
+ f ['include' ] = False
860
+ break
861
+
914
862
files = [f for f in files
915
- if f ['action' ] != 'delete' ]
863
+ if f ['action' ] != 'delete' and
864
+ (f .has_key ('include' ) == False or f ['include' ] == True )]
916
865
917
866
if not files :
918
- return
867
+ return []
919
868
920
869
filedata = p4CmdList ('-x - print' ,
921
870
stdin = '\n ' .join (['%s#%s' % (f ['path' ], f ['rev' ])
@@ -950,6 +899,7 @@ class P4Sync(Command):
950
899
for f in files :
951
900
assert not f .has_key ('data' )
952
901
f ['data' ] = contents [f ['path' ]]
902
+ return files
953
903
954
904
def commit (self , details , files , branch , branchPrefixes , parent = "" ):
955
905
epoch = details ["time" ]
@@ -966,11 +916,7 @@ class P4Sync(Command):
966
916
new_files .append (f )
967
917
else :
968
918
sys .stderr .write ("Ignoring file outside of prefix: %s\n " % path )
969
- files = new_files
970
- self .readP4Files (files )
971
-
972
-
973
-
919
+ files = self .readP4Files (new_files )
974
920
975
921
self .gitStream .write ("commit %s\n " % branch )
976
922
# gitStream.write("mark :%s\n" % details["change"])
@@ -1385,6 +1331,26 @@ class P4Sync(Command):
1385
1331
print self .gitError .read ()
1386
1332
1387
1333
1334
+ def getClientSpec (self ):
1335
+ specList = p4CmdList ( "client -o" )
1336
+ temp = {}
1337
+ for entry in specList :
1338
+ for k ,v in entry .iteritems ():
1339
+ if k .startswith ("View" ):
1340
+ if v .startswith ('"' ):
1341
+ start = 1
1342
+ else :
1343
+ start = 0
1344
+ index = v .find ("..." )
1345
+ v = v [start :index ]
1346
+ if v .startswith ("-" ):
1347
+ v = v [1 :]
1348
+ temp [v ] = - len (v )
1349
+ else :
1350
+ temp [v ] = len (v )
1351
+ self .clientSpecDirs = temp .items ()
1352
+ self .clientSpecDirs .sort ( lambda x , y : abs ( y [1 ] ) - abs ( x [1 ] ) )
1353
+
1388
1354
def run (self , args ):
1389
1355
self .depotPaths = []
1390
1356
self .changeRange = ""
@@ -1417,6 +1383,9 @@ class P4Sync(Command):
1417
1383
if not gitBranchExists (self .refPrefix + "HEAD" ) and self .importIntoRemotes and gitBranchExists (self .branch ):
1418
1384
system ("git symbolic-ref %sHEAD %s" % (self .refPrefix , self .branch ))
1419
1385
1386
+ if self .useClientSpec or gitConfig ("p4.useclientspec" ) == "true" :
1387
+ self .getClientSpec ()
1388
+
1420
1389
# TODO: should always look at previous commits,
1421
1390
# merge with previous imports, if possible.
1422
1391
if args == []:
@@ -1634,13 +1603,23 @@ class P4Clone(P4Sync):
1634
1603
P4Sync .__init__ (self )
1635
1604
self .description = "Creates a new git repository and imports from Perforce into it"
1636
1605
self .usage = "usage: %prog [options] //depot/path[@revRange]"
1637
- self .options . append (
1606
+ self .options += [
1638
1607
optparse .make_option ("--destination" , dest = "cloneDestination" ,
1639
1608
action = 'store' , default = None ,
1640
- help = "where to leave result of the clone" ))
1609
+ help = "where to leave result of the clone" ),
1610
+ optparse .make_option ("-/" , dest = "cloneExclude" ,
1611
+ action = "append" , type = "string" ,
1612
+ help = "exclude depot path" )
1613
+ ]
1641
1614
self .cloneDestination = None
1642
1615
self .needsGit = False
1643
1616
1617
+ # This is required for the "append" cloneExclude action
1618
+ def ensure_value (self , attr , value ):
1619
+ if not hasattr (self , attr ) or getattr (self , attr ) is None :
1620
+ setattr (self , attr , value )
1621
+ return getattr (self , attr )
1622
+
1644
1623
def defaultDestination (self , args ):
1645
1624
## TODO: use common prefix of args?
1646
1625
depotPath = args [0 ]
@@ -1664,6 +1643,7 @@ class P4Clone(P4Sync):
1664
1643
self .cloneDestination = depotPaths [- 1 ]
1665
1644
depotPaths = depotPaths [:- 1 ]
1666
1645
1646
+ self .cloneExclude = ["/" + p for p in self .cloneExclude ]
1667
1647
for p in depotPaths :
1668
1648
if not p .startswith ("//" ):
1669
1649
return False
0 commit comments