0
-# Created by Dan Preston on 4/09/08.
0
-import sys, commands, os, tempfile, filecmp
0
-from optparse import OptionParser
0
-gToolName = "git-bbedit-diff"
0
-gdiffVersion = gToolName + " version 1.2"
0
-gConflictMarker = ".CONFLICT"
0
-gTheirsMarker = ".THEIRS"
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def fileNotPresentError(repositoryPath, revision, chatty=True):
0
- print "\tFile \"%s\" does not exist in repository at revision \"%s\"." % (repositoryPath, revision)
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-# createTempFileForRevision
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def createTempFileForRevision( revision, repositoryPath, chatty=True ):
0
- # Escape the path with quotes to handle the case where we have spaces.
0
- command = "git show " + revision + ':"' + repositoryPath + '"'
0
- # Use git show to get the contents of the head of the file.
0
- status, output = commands.getstatusoutput( command )
0
- fileNotPresentError( repositoryPath, revision, chatty )
0
- # git show doesn't seem to append the final carriage return.
0
- output = output + "\n"
0
- # Create the temp file name and write out the temp file.
0
- nameRoot, extension = os.path.splitext( repositoryPath )
0
- _, fileName = os.path.split( nameRoot )
0
- temp = tempfile.mktemp( "_" + fileName + extension, gToolName + "-" + revision + "_", gTempDir )
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def performDiff(compareFile, revision, chatty=True):
0
- # Check that we have enough arguments.
0
- revision, _, revision2 = revision.partition("..")
0
- realpath = os.path.abspath( compareFile )
0
- head, relativePath = os.path.split( realpath )
0
- fileName = relativePath
0
- if os.path.isdir( realpath ):
0
- print "\t\"" + relativePath + "\" is a directory. " + gToolName + " only compares files."
0
- # Figure out what the relative path of the file is from the .git folder.
0
- while (found == False) and (head != "/"):
0
- gitPath = os.path.join( head, ".git" )
0
- found = os.path.exists( gitPath )
0
- head, tail = os.path.split( head )
0
- relativePath = os.path.join( tail, relativePath )
0
- # Make sure we are actually in a git repository.
0
- if (found == False) and (head == "/"):
0
- print "\tThat file is not in a git repository."
0
- file1 = createTempFileForRevision( revision, relativePath, chatty )
0
- file2 = createTempFileForRevision( revision2, relativePath, chatty )
0
- if os.path.exists(file2) == False:
0
- fileNotPresentError( relativePath, "HEAD", chatty )
0
- if (file1 == None) or (file2 == None):
0
- same = filecmp.cmp( file2, file1 )
0
- print "\tThe file \"" + fileName + "\" has no differences."
0
- # Escape the files with quotes to allow for files with spaces.
0
- command = 'bbdiff "%s" "%s"' % ( file2, file1 )
0
- status, output = commands.getstatusoutput( command )
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def cleanTmpDirectory(chatty=True):
0
- tempContents = os.listdir( gTempDir )
0
- for tmpFile in tempContents:
0
- if tmpFile.startswith( gToolName + "-" ):
0
- filePath = gTempDir + tmpFile
0
- print "\tRemoving temp file:\"%s\"" % filePath
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def numConflicts(conflictFile):
0
- f = open(conflictFile, "r")
0
- if line.startswith("<<<<<<<") and (foundStart == False) and (foundMiddle == False):
0
- if line.startswith("=======") and foundStart and (foundMiddle == False):
0
- if line.startswith(">>>>>>>") and foundStart and foundMiddle:
0
- conflicts = conflicts + 1
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def uniqueName(path, uniqueLabel):
0
- base, extension = os.path.splitext(path)
0
- if os.path.exists(base + uniqueLabel + uniqueDigit + extension):
0
- uniqueDigit = str(digit)
0
- newPath = base + uniqueLabel + uniqueDigit + extension
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def createConflictFiles(minePath, theirPath, conflictFile):
0
- orig = open(conflictFile, "r")
0
- mine = open(minePath, "w")
0
- theirs = open(theirPath, "w")
0
- line = orig.readline()
0
- if line.startswith("<<<<<<<") and placeInTheirs and placeInMine:
0
- elif line.startswith("=======") and placeInTheirs and (placeInMine == False):
0
- elif line.startswith(">>>>>>>") and (placeInTheirs == False) and placeInMine:
0
- line = orig.readline()
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def diffConflict(conflictFile, chatty=True):
0
- conflicts = numConflicts(conflictFile)
0
- if (conflicts == 0) and chatty:
0
- basePath, fileName = os.path.split( conflictFile )
0
- print "\tThe file \"%s\" does not contain any conflicts. SKIPPING." % fileName
0
- newConflictPath = uniqueName(conflictFile, gConflictMarker)
0
- os.rename(conflictFile, newConflictPath)
0
- theirPath = uniqueName(conflictFile, gTheirsMarker)
0
- createConflictFiles(conflictFile, theirPath, newConflictPath)
0
- command = 'bbdiff "%s" "%s"' % ( conflictFile, theirPath )
0
- status, output = commands.getstatusoutput( command )
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-# cleanConflictRelatedFiles
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-def cleanConflictRelatedFiles(conflictFile, chatty=True):
0
- filePath, extension = os.path.splitext( conflictFile )
0
- # Remove .CONFLICT files.
0
- tempfile = filePath + gConflictMarker + extension
0
- if os.path.exists( tempfile ):
0
- _, base = os.path.split( filePath )
0
- base = base + gConflictMarker + extension
0
- print "\tDeleting file \"%s\"." % base
0
- command = "rm " + tempfile
0
- #remove .THEIRS files.
0
- tempfile = filePath + gTheirsMarker + extension
0
- if os.path.exists( tempfile ):
0
- _, base = os.path.split( filePath )
0
- base = base + gTheirsMarker + extension
0
- print "\tDeleting file \"%s\"." % base
0
- command = "rm " + tempfile
0
-#----------------------------------------------------------------------------------------------------------------------------
0
-#----------------------------------------------------------------------------------------------------------------------------
0
- # Set up options for the command line that we support.
0
- description="A utility to compare files in a git repository using bbedit."
0
- usage = "usage: %prog [--version] | [-h | --help] | [-q | --quiet] [--clean] [[-c | --conflict] | [-r | --revision <revision(s)>]] file1 [file2 ...]"
0
- parser = OptionParser(version=gdiffVersion, description=description, usage=usage)
0
- parser.add_option("-r", "--revision", dest="revision", help="Pass a revision or a revision range using the git syntax (ie: 98d4cf..bfced5) for " + gToolName + " to compare. This option is mutually exclusive to the '-c' option.")
0
- parser.add_option("--clean", action="store_true", dest="cleanUp", default=False, help="Delete all of the temp files that " + gToolName + " has created. If any files are passed as arguments, their --conflict related files (\"" + gConflictMarker + "\", \"" + gTheirsMarker + "\") will be deleted.")
0
- parser.add_option("-q", "--quiet", action="store_false", dest="chatty", default=True, help="Reduce the chatter of " + gToolName + ".")
0
- parser.add_option("-c", "--conflict", action="store_true", dest="conflict", default=False, help="The files being diffed have conflict markers that need to be resolved. This option is mutually exclusive to the '-r' option.")
0
- (options, args) = parser.parse_args(argv[1:])
0
- cleanTmpDirectory(options.chatty)
0
- cleanConflictRelatedFiles(gitFile, options.chatty)
0
- # These options are mutually exclusive.
0
- if options.revision and options.conflict:
0
- # See if we can see any reason that we need to print the usage for the app.
0
- print "Diffing Conflict \"%s\"." % gitFile
0
- diffConflict(gitFile, options.chatty)
0
- rev = options.revision
0
- print "Comparing \"%s\"." % gitFile
0
- performDiff(gitFile, rev, options.chatty)
0
-if __name__ == "__main__":
Comments
No one has commented yet.