Skip to content

Commit

Permalink
gitdist: Add Default Development Branch... (TriBITSPub#235)
Browse files Browse the repository at this point in the history
Here's an initial implementation that allows a user to add default
development branches to the .gitdist file in the form

. master
otherRepo develop
thirdRepo master

If those default development branches aren't specified, master is
assumed.  The user can then pass _DEFAULT_BRANCH_ to any command that
accepts a reference and gitdist should replace _DEFAULT_BRANCH_ with the
appropriate branch from the .gitdist file.  The documentation for this
feature can be accessed with --dist-help=default-branch.
  • Loading branch information
jmgate committed Nov 2, 2017
1 parent 3b2f98a commit 432f3aa
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 11 deletions.
75 changes: 73 additions & 2 deletions test/python_utils/gitdist_UnitTests.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,8 @@ def assertContainsAllGitdistHelpSections(testObj, cmndOut):
GeneralScriptSupport.extractLinesMatchingRegex(cmndOut,"^USAGE TIPS:$"), "USAGE TIPS:\n")
testObj.assertEqual(
GeneralScriptSupport.extractLinesMatchingRegex(cmndOut,"^SCRIPT DEPENDENCIES:$"), "SCRIPT DEPENDENCIES:\n")
testObj.assertEqual(
GeneralScriptSupport.extractLinesMatchingRegex(cmndOut,"^SCRIPT DEPENDENCIES:$"), "DEFAULT BRANCH SPECIFICATION:\n")


class test_gitdist(unittest.TestCase):
Expand Down Expand Up @@ -676,15 +678,15 @@ def test_dist_help_all_help(self):
# Tet that --dist-help --help prints nice error message
def test_dist_help_help(self):
cmndOut = getCmndOutput(gitdistPath+" --dist-help --help")
cmndOut_expected = "gitdist: error: option --dist-help: invalid choice: '--help' (choose from '', 'overview', 'repo-selection-and-setup', 'dist-repo-status', 'repo-versions', 'aliases', 'usage-tips', 'script-dependencies', 'all')\n"
cmndOut_expected = "gitdist: error: option --dist-help: invalid choice: '--help' (choose from '', 'overview', 'repo-selection-and-setup', 'dist-repo-status', 'repo-versions', 'aliases', 'usage-tips', 'script-dependencies', 'default-branch', 'all')\n"
self.assertEqual(s(cmndOut), s(cmndOut_expected))


# Test --dist-helps=invalid-pick picked up as invalid value.
def test_dist_help_invalid_pick_help(self):
cmndOut = getCmndOutput(gitdistPath+" --dist-help=invalid-pick --help")
assertContainsGitdistHelpHeader(self, cmndOut)
errorToFind = "gitdist: error: option --dist-help: invalid choice: 'invalid-pick' (choose from '', 'overview', 'repo-selection-and-setup', 'dist-repo-status', 'repo-versions', 'aliases', 'usage-tips', 'script-dependencies', 'all')"
errorToFind = "gitdist: error: option --dist-help: invalid choice: 'invalid-pick' (choose from '', 'overview', 'repo-selection-and-setup', 'dist-repo-status', 'repo-versions', 'aliases', 'usage-tips', 'script-dependencies', 'default-branch', 'all')"
self.assertEqual(
GeneralScriptSupport.extractLinesMatchingSubstr(cmndOut,errorToFind), errorToFind+"\n")

Expand Down Expand Up @@ -1400,5 +1402,74 @@ def test_dist_repo_status_extra_args_fail(self):
os.chdir(testBaseDir)


def test_dist_default_branch(self):
os.chdir(testBaseDir)
try:

# Create a mock git meta-project

testDir = createAndMoveIntoTestDir("gitdist_default_branch")
os.mkdir("ExtraRepo1")
os.makedirs("Path/To/ExtraRepo2")
os.mkdir("ExtraRepo3")

# Make sure .gitdist.default is found and read correctly
open(".gitdist.default", "w").write(
". master\n" \
"ExtraRepo1 develop\n" \
"Path/To/ExtraRepo2 app-devel\n" \
"MissingExtraRepo\n" \
"ExtraRepo3\n"
)
cmndOut = GeneralScriptSupport.getCmndOutput(
gitdistPathMock+" checkout _DEFAULT_BRANCH_", workingDir=testDir)
cmndOut_expected = \
"\n*** Base Git Repo: MockProjectDir\n" \
"['mockgit', 'checkout', 'master']\n\n" \
"*** Git Repo: ExtraRepo1\n" \
"['mockgit', 'checkout', 'develop']\n\n" \
"*** Git Repo: Path/To/ExtraRepo2\n" \
"['mockgit', 'checkout', 'app-devel']\n\n" \
"*** Git Repo: ExtraRepo3\n" \
"['mockgit', 'checkout', 'master']\n\n"
self.assertEqual(s(cmndOut), s(cmndOut_expected))
# NOTE: Above ensures that all of the paths are read correctly and that
# missing paths (MissingExtraRepo) are ignored.

# Make sure that .gitdist overrides .gitdist.default
open(".gitdist", "w").write(
". develop\n" \
"ExtraRepo1 develop\n" \
"ExtraRepo3 develop\n"
)
cmndOut = GeneralScriptSupport.getCmndOutput(
gitdistPathMock+" checkout _DEFAULT_BRANCH_", workingDir=testDir)
cmndOut_expected = \
"\n*** Base Git Repo: MockProjectDir\n" \
"['mockgit', 'checkout', 'develop']\n\n" \
"*** Git Repo: ExtraRepo1\n" \
"['mockgit', 'checkout', 'develop']\n\n" \
"*** Git Repo: ExtraRepo3\n" \
"['mockgit', 'checkout', 'develop']\n\n"
self.assertEqual(s(cmndOut), s(cmndOut_expected))

# Make sure that --dist-repos overrides all files
cmndOut = GeneralScriptSupport.getCmndOutput(
gitdistPathMock+" --dist-repos=.,ExtraRepo1,Path/To/ExtraRepo2 "+ \
"checkout _DEFAULT_BRANCH_",
workingDir=testDir)
cmndOut_expected = \
"\n*** Base Git Repo: MockProjectDir\n" \
"['mockgit', 'checkout', 'master']\n\n" \
"*** Git Repo: ExtraRepo1\n" \
"['mockgit', 'checkout', 'master']\n\n" \
"*** Git Repo: Path/To/ExtraRepo2\n" \
"['mockgit', 'checkout', 'master']\n\n"
self.assertEqual(s(cmndOut), s(cmndOut_expected))

finally:
os.chdir(testBaseDir)


if __name__ == '__main__':
unittest.main()
95 changes: 86 additions & 9 deletions tribits/python_utils/gitdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ def s(x):
'repo-versions',
'aliases',
'usage-tips',
'script-dependencies'
'script-dependencies',
'default-branch'
]


Expand Down Expand Up @@ -613,6 +614,47 @@ def getHelpTopicsStr():
helpTopicsDict.update( { 'script-dependencies' : scriptDependenciesHelp } )


defaultBranchHelp = r"""
DEFAULT BRANCH SPECIFICATION:
When using any git command that accepts a reference (a SHA1, or branch or tag
name), it is possible to use _DEFAULT_BRANCH_ instead. For instance,
gitdist checkout _DEFAULT_BRANCH_
will check out the default development branch in each repository being managed
by gitdist. You can specify the default branch for each repository in your
.gitdist[.default] file. For instance, if your .gitdist file contains
. master
extraRepo1 develop
extraRepo2 app-devel
then the command above would check out master in the base repo, develop in
extraRepo1, and app-devel in extraRepo2. This makes it convenient when working
with multiple repositories that have different names for their main development
branches. For instance, you can
gitdist checkout _DEFAULT_BRANCH_
gitdist pull
gitdist checkout -b newFeatureBranch
# do some work
gitdist fetch
gitdist merge _DEFAULT_BRANCH_
# do some more work
gitdist checkout _DEFAULT_BRANCH_
gitdist pull
gitdist merge newFeatureBranch
and not worry about this newFeatureBranch being off of master in the root repo,
off of develop in extraRepo1, and off of app-devel in extraRepo2.
If no branch name is specified for any given repository in the
.gitdist[.default] file, then master is assumed.
"""
helpTopicsDict.update( { 'default-branch' : defaultBranchHelp } )


#
# Functions to help Format an ASCII table
#
Expand Down Expand Up @@ -819,6 +861,22 @@ def addColorToErrorMsg(useColor, strIn):
return strIn


# Get the paths to all the repos gitdist will work on, along with any optional
# default branches.
def parseGitdistFile(gitdistfile):
reposFullList = []
defaultBranchDict = {}
with open(gitdistfile, 'r') as file:
for line in file:
entries = line.split()
reposFullList.append(entries[0])
if len(entries) > 1:
defaultBranchDict[entries[0]] = entries[1]
else:
defaultBranchDict[entries[0]] = "master"
return (reposFullList, defaultBranchDict)


# Get the commandline options
def getCommandlineOps():

Expand Down Expand Up @@ -1075,6 +1133,9 @@ def getCommandlineOps():

if options.repos:
reposFullList = options.repos.split(",")
defaultBranchDict = {}
for repo in reposFullList:
defaultBranchDict[repo] = "master"
else:
if os.path.exists(".gitdist"):
gitdistfile = ".gitdist"
Expand All @@ -1083,9 +1144,10 @@ def getCommandlineOps():
else:
gitdistfile = None
if gitdistfile:
reposFullList = open(gitdistfile, 'r').read().split()
(reposFullList, defaultBranchDict) = parseGitdistFile(gitdistfile)
else:
reposFullList = ["."] # The default is the base repo
defaultBranchDict = {".": "master"}

# Get list of not extra repos

Expand All @@ -1098,7 +1160,7 @@ def getCommandlineOps():
# G) Return
#

return (options, nativeCmnd, otherArgs, reposFullList,
return (options, nativeCmnd, otherArgs, reposFullList, defaultBranchDict,
notReposFullList)


Expand Down Expand Up @@ -1205,13 +1267,28 @@ def replaceRepoVersionInCmndLineArgs(cmndLineArgsArray, repoDirName, \
return cmndLineArgsArrayRepo


# Replace _DEFAULT_BRANCH_ in the command line arguments with the appropriate
# default branch name.
def replaceDefaultBranchInCmndLineArgs(cmndLineArgsArray, repoDirName, \
defaultBranchDict \
):
cmndLineArgsArrayDefaultBranch = []
for cmndLineArg in cmndLineArgsArray:
newCmndLineArg = re.sub("_DEFAULT_BRANCH_", \
defaultBranchDict[repoDirName], cmndLineArg)
cmndLineArgsArrayDefaultBranch.append(newCmndLineArg)
return cmndLineArgsArrayDefaultBranch


# Generate the command line arguments
def runRepoCmnd(options, cmndLineArgsArray, repoDirName, baseDir, \
repoVersionDict, repoVersionDict2 \
repoVersionDict, repoVersionDict2, defaultBranchDict \
):
cmndLineArgsArryRepo = replaceRepoVersionInCmndLineArgs(cmndLineArgsArray, \
cmndLineArgsArrayRepo = replaceRepoVersionInCmndLineArgs(cmndLineArgsArray, \
repoDirName, repoVersionDict, repoVersionDict2)
egCmndArray = [ options.useGit ] + cmndLineArgsArryRepo
cmndLineArgsArrayDefaultBranch = replaceDefaultBranchInCmndLineArgs( \
cmndLineArgsArrayRepo, repoDirName, defaultBranchDict)
egCmndArray = [ options.useGit ] + cmndLineArgsArrayDefaultBranch
runCmnd(options, egCmndArray)


Expand Down Expand Up @@ -1423,8 +1500,8 @@ def getRepoName(repoDir, baseRepoName):

if __name__ == '__main__':

(options, nativeCmnd, otherArgs, reposFullList, notReposList) = \
getCommandlineOps()
(options, nativeCmnd, otherArgs, reposFullList, defaultBranchDict, \
notReposList) = getCommandlineOps()

if nativeCmnd == "dist-repo-status":
distRepoStatus = True
Expand Down Expand Up @@ -1496,7 +1573,7 @@ def getRepoName(repoDir, baseRepoName):
print("*** Tracking branch for git repo '" + repoName + "' = '" +
repoStats.trackingBranch + "'")
runRepoCmnd(options, cmndLineArgsArray, repo, baseDir, \
repoVersionDict, repoVersionDict2)
repoVersionDict, repoVersionDict2, defaultBranchDict)
if options.debug:
print("*** Changing to directory " + baseDir)

Expand Down

0 comments on commit 432f3aa

Please sign in to comment.