def LoadFilteredPackageDescs(args): categories = [] matchAll = ughubUtil.HasCommandlineOption(args, ("-a", "--matchall")) installed = ughubUtil.HasCommandlineOption(args, ("-i", "--installed")) notinstalled = ughubUtil.HasCommandlineOption(args, ("-n", "--notinstalled")) sourceName = ughubUtil.GetCommandlineOptionValue(args, ("-s", "--source")) for arg in args: if arg[0] != "-": categories.append(arg) else: break try: allPackages = LoadPackageDescs(sourceName) if len(allPackages) == 0: return allPackages packages = [] # select according to installed/notinstalled if installed and notinstalled: print("Cannot use --installed and --notinstalled simultaneously.") raise Exception() if installed: for pkg in allPackages: if PackageIsInstalled(pkg): packages.append(pkg) if notinstalled: for pkg in allPackages: if not PackageIsInstalled(pkg): packages.append(pkg) if not installed and not notinstalled: for pkg in allPackages: packages.append(pkg) # select according to category if matchAll: packages = FilterPackagesAll(packages, categories) elif len(categories) > 0: packages = FilterPackagesAny(packages, categories) return packages except LookupError as e: raise InvalidPackageError(e)
def PrintPackageInfo(args): packageList = ughubUtil.RemoveOptions(args) if len(packageList) != 1: print("Please specify exactly one package name. See 'ughub help packageinfo'") return packageName = packageList[0] packages = LoadPackageDescs() firstPackage = True for pkg in packages: try: if pkg["name"] == packageName: if not firstPackage: print("") firstPackage = False print("package '{0}' from source '{1}':" .format(packageName, pkg["__SOURCE"])) if ughubUtil.HasCommandlineOption(args, ("-s", "--short")): print(ShortPackageInfo(pkg)) else: print(LongPackageInfo(pkg)) except LookupError: raise InvalidSourceError("Failed to access package list in '{0}'" .format(packagesFile))
def InitializeDirectory(args): force = ughubUtil.HasCommandlineOption(args, ("-f", "--force")) rootPath = os.getcwd() if len(args) > 0 and args[0][0] != '-': if os.path.isabs(args[0]): rootPath = args[0] else: rootPath = os.path.join(rootPath, args[0]) ughubPath = os.path.normpath(os.path.join(rootPath, ".ughub")) if os.path.isdir(ughubPath): if os.path.isfile(os.path.join(ughubPath, "sources.json")): print("Directory '{0}' has been initialized already.".format(ughubPath)) return else: try: existingRootDir = GetRootDirectory(ughubPath) if not force: print("Warning: Found ughub root directory at: {0}".format(existingRootDir)) print("call 'ughub init -f' to force initialization in this path.") return except NoRootDirectoryError: pass # this is actually the expected case os.makedirs(ughubPath) GenerateDefaultSourceFile(ughubPath) UpdateSources([], ughubPath) GenerateCMakeLists(rootPath) print("initialized ughub directory at '{0}'".format(rootPath))
def GenerateProjectFiles(args): options = [] for i in range(len(args)): if args[i][0] == "-": options = args[i:] args = args[0:i] break if len(args) < 1: raise ArgumentError("Please specify a TARGET.") name = ughubUtil.GetCommandlineOptionValue(args, ("-n", "--name")) overwriteFiles = ughubUtil.HasCommandlineOption(options, ("-o", "--overwrite")) deleteFiles = ughubUtil.HasCommandlineOption(options, ("-d", "--delete")) if deleteFiles: ughubProjectFileGenerator.RemoveFiles(GetRootDirectory(), args[0]) else: ughubProjectFileGenerator.Run(GetRootDirectory(), args[0], name, overwriteFiles)
def ListPackages(args): categories = [] matchAll = ughubUtil.HasCommandlineOption(args, ("-a", "--matchall")) for arg in args: if arg[0] != "-": categories.append(arg) try: packages = LoadPackageDescs() if len(packages) == 0: print("no packages found") return if matchAll: packages = FilterPackagesAll(packages, categories) elif len(categories) > 0: packages = FilterPackagesAny(packages, categories) if len(packages) == 0: print("no packages found for the given criteria") return # sort packages alphabetically packageDict = {} for pkg in packages: packageDict[pkg["name"]] = packageDict.get(pkg["name"], []) + [pkg] print("{0:24.4} {1:10} {2:11} {3:}".format("NAME", "PREFIX", "SOURCE", "URL")) for key in sorted(packageDict.keys()): pkgs = packageDict[key] for pkg in pkgs: print("{0:24} {1:10} {2:11} {3:}".format( pkg["name"], pkg["prefix"], pkg["__SOURCE"], pkg["url"])) except LookupError as e: raise InvalidPackageError(e)
def ListPackages(args): try: packages = LoadFilteredPackageDescs(args) if len(packages) == 0: print("no packages found") return # sort packages alphabetically packageDict = {} for pkg in packages: packageDict[pkg["name"]] = packageDict.get(pkg["name"], []) + [pkg] namesonly = ughubUtil.HasCommandlineOption(args, ("--namesonly", )) if namesonly: result = "" for key in sorted(packageDict.keys()): pkgs = packageDict[key] for pkg in pkgs: result += pkg["name"] + " " ughubUtil.Write(result) else: print("{0:24.4} {1:10} {2:11} {3:}".format( "NAME", "PREFIX", "SOURCE", "URL")) for key in sorted(packageDict.keys()): pkgs = packageDict[key] for pkg in pkgs: print("{0:24} {1:10} {2:11} {3:}".format( pkg["name"], pkg["prefix"], pkg["__SOURCE"], pkg["url"])) except LookupError as e: raise InvalidPackageError(e)
def PrintCommandHelp(cmdName, args=[]): shortdesc = ughubUtil.HasCommandlineOption(args, ("--short", )) try: cmdDict = GetHelpEntry("commands.{0}".format(cmdName)) except ughubUtil.NestedTableEntryNotFoundError: raise MalformedHelpContentsError( "Requested command '{0}' not found in help database".format( cmdName)) if shortdesc: if "shortdescription" in cmdDict: ughubUtil.Write(cmdDict["shortdescription"]) return print("Usage: ughub {0}".format(cmdDict["usage"])) print("") for line in cmdDict["description"].splitlines(): print(" {0}".format(line)) try: options = ughubUtil.GetFromNestedTable(cmdDict, "options") except ughubUtil.NestedTableEntryNotFoundError: return print("") print("Valid options:") for opt in options: name = opt["name"] sep = ":" for line in opt["description"].splitlines(): print(" {0:20}{1} {2}".format(name, sep, line)) name = "" sep = " "
def InstallPackage(args): packageNames = args options = [] for i in range(len(args)): if args[i][0] == "-": packageNames = args[0:i] options = args[i:] break if len(packageNames) == 0: print("Please specify a package name. See 'ughub help install'.") return dryRun = ughubUtil.HasCommandlineOption(options, ("-d", "--dry")) force = ughubUtil.HasCommandlineOption(options, ("-f", "--force")) resolve = ughubUtil.HasCommandlineOption(options, ("-r", "--resolve")) branch = ughubUtil.GetCommandlineOptionValue(options, ("-b", "--branch")) source = ughubUtil.GetCommandlineOptionValue(options, ("-s", "--source")) packages = LoadPackageDescs() rootDir = GetRootDirectory() requiredPackages = [] processedPackageBranchPairs = [] for packageName in packageNames: requiredPackages = requiredPackages + BuildPackageDependencyList(packageName, packages, source, branch, processedPackageBranchPairs) print("List of required packages:") #0: Message, 1: Package name, 2: current remote, 3: required remote textRemoteConflictUF = ("" "{0}: Url of remote 'origin' of package '{1}' does not correspond\n" " to the current source-definition:\n" " currentt URL: '{2}'\n" " expected URL: '{3}'\n" " This is most likely a result of an updated source-definition (e.g. through 'ughub updatesources').") #0: required remote, 2: package-path textRemoteConflictOptionsUF = ("" " You may\n" " - call 'ughub install ...' with the '--resolve' option to resolve conflicts on the fly.\n" " - manually adjust the url by executing\n" " 'git remote set-url origin {0}'\n" " at '{1}'\n" " - call 'ughub install ...' with the '--force' option to force installation despite this\n" " error. This may result in an outdated package and build conflicts!") #0: Message, 1: Package name, 2: current branch, 3: required branch textBranchConflictUF = ("" "{0}: Current branch '{2}' of installed package '{1}'\n" " does not correspond to the required branch '{3}'.") #0: required branch, 2: package-path textBranchConflictOptionsUF = ("" " You may\n" " - call 'ughub install' with the '--resolve' option to automatically resolve the conflict\n" " (a checkout of the required branch will be performed).\n" " - manually check out the required branch by executing\n" " git checkout {0}\n" " at '{1}'\n" " - call 'ughub install' with the '--force' option to ignore the error. This may lead to build problems!\n") # iterate over all required packages. Check for each whether it already # exists and whether the branch matches. # If it doesn't exist, perform a fresh clone. # If it does exist and branches match, perform a pull. # If it does exist but branches mismatch, perform a pull if --force was specified # and abort with a warning if it wasn't specified. firstPkg = True problemsOccurred = False for pkg in requiredPackages: if not firstPkg: print("") firstPkg = False print(ShortPackageInfo(pkg)) # check whether the package is already installed if pkg["repoType"] == "git": prefixPath = os.path.join(rootDir, pkg["prefix"]) pkgPath = os.path.join(prefixPath, pkg["name"]) if os.path.isdir(os.path.join(pkgPath, ".git")): # The package exists. validate its origin. fetchURL, pushURL = GetCurrentRemoteGitURLs(pkg) if fetchURL != pkg["url"] or pushURL != pkg["url"]: if fetchURL != pkg["url"]: wrongURL = fetchURL if pushURL != pkg["url"]: wrongURL = pushURL problemsOccurred = True if resolve: print(textRemoteConflictUF.format("NOTE", pkg["name"], wrongURL, pkg["url"])) print("The remote will be automatically adjusted (--resolve)") if not dryRun: proc = subprocess.Popen(["git","remote","set-url","origin", pkg["url"]], cwd = pkgPath) if proc.wait() != 0: raise TransactionError("Couldn't set url '{0}' of remote 'origin' for package '{1}' at '{2}'" .format(pkg["url"], pkg["name"], pkgPath)) elif force: print(textRemoteConflictUF.format("WARNING", pkg["name"], wrongURL, pkg["url"])) print("The warning will be ignored (--force). This may result in an outdated package and build conflicts!") else: text = textRemoteConflictUF.format("ERROR", pkg["name"], wrongURL, pkg["url"]) + "\n" + textRemoteConflictOptionsUF.format(pkg["url"], pkgPath) if dryRun: print(text) else: raise DependencyError(text) # Validate branch p = subprocess.Popen("git branch".split(), cwd = pkgPath, stdout=subprocess.PIPE) gitLog = p.communicate()[0].decode("utf-8") if p.returncode != 0: raise TransactionError("Couldn't access branch information of package '{0}' at '{1}'" .format(pkg["name"], pkgPath)) curBranch = None for line in gitLog.splitlines(): if line[0] == "*": curBranch = line.split()[1] break if curBranch != pkg["__BRANCH"]: problemsOccurred = True if resolve: print(textBranchConflictUF.format("NOTE", pkg["name"], curBranch, pkg["__BRANCH"])) print("The required branch will be automatically checked out (--resolve)") if not dryRun: proc = subprocess.Popen(["git", "checkout", pkg["__BRANCH"]], cwd = pkgPath) if proc.wait() != 0: raise TransactionError("Trying to resolve branch conflict but couldn't check " "out branch '{0}' of package '{1}' at '{2}'" .format(pkg["__BRANCH"], pkg["name"], pkgPath)) elif force: print(textBranchConflictUF.format("WARNING", pkg["name"], curBranch, pkg["__BRANCH"])) print("The warning will be ignored (--force). This may result in build problems!") else: text = textBranchConflictUF.format("ERROR", pkg["name"], curBranch, pkg["__BRANCH"]) + "\n" + textBranchConflictOptionsUF.format(pkg["__BRANCH"], pkgPath) if dryRun: print(text) else: raise DependencyError(text) # if dryRun: # if resolve: # print("NOTE: Branch '{0}' of package '{2}' at '{3}'\n" # " will be replaced by branch '{1}' (--resove)" # .format(curBranch, pkg["__BRANCH"], pkg["name"], pkgPath)) # elif force: # print("WARNING: Branch conflict between current branch '{0}' and required\n" # "branch '{1}' of package '{2}' at '{3}' will be ignored (--force)." # .format(curBranch, pkg["__BRANCH"], pkg["name"], pkgPath)) # else: # problemsOccurred = True # print("ERROR: Current branch '{0}' and required branch '{1}'\n" # " do not match for package '{2}' at '{3}'.\n" # " - Call 'ughub install' with the '--resolve' option to force a checkout of the required branch.\n" # " - Call 'ughub install' with the '--force' option to ignore the error. This may lead to build problems!\n" # .format(curBranch, pkg["__BRANCH"], pkg["name"], pkgPath))) # else: # if resolve: # proc = subprocess.Popen(["git", "checkout", pkg["__BRANCH"]], cwd = pkgPath) # if proc.wait() != 0: # raise TransactionError("Trying to resolve branch conflict but couldn't check " # "out branch '{0}' of package '{1}' at '{2}'" # .format(pkg["__BRANCH"], pkg["name"], pkgPath)) # print("Resolved branch conflict by switching from branch '{0}'\n" # "to branch '{1}' of package '{2}' at '{3}' (--resolve)" # .format(curBranch, pkg["__BRANCH"], pkg["name"], pkgPath)) # elif force: # print("WARNING: Ignoring branch conflict between current branch '{0}'\n" # "and required branch '{1}' of package '{2}' at '{3}' (--force)" # .format(curBranch, pkg["__BRANCH"], pkg["name"], pkgPath)) # else: # raise DependencyError( # "Current branch '{0}' and required branch '{1}'\n" # " do not match for package '{2}' at '{3}'.\n" # " - Call 'ughub install' with the '--resolve' option to force a checkout of the required branch.\n" # " - Call 'ughub install' with the '--force' option to ignore the error. This may lead to build problems!\n" # .format(curBranch, pkg["__BRANCH"], pkg["name"], pkgPath)) if not dryRun: proc = subprocess.Popen(["git", "pull"], cwd = pkgPath) if proc.wait() != 0: raise TransactionError("Couldn't pull for package '{0}' at '{1}'" .format(pkg["name"], pkgPath)) else: # the package doesn't exist yet. Make sure that all paths are set up correctly # and perform a clone if os.path.exists(pkgPath): try: if not os.path.isdir(pkgPath): raise TargetError("Target path '{0}' for package '{1}' exists but is not a directory" .format(pkgPath, pkg["name"])) if os.listdir(pkgPath): raise TargetError("Target path '{0}' for package '{1}' has to be empty or a valid git working copy." .format(pkgPath, pkg["name"])) except TargetError as e: if dryRun: print("WARNING: {0}".format(e)) problemsOccurred = True else: raise e if not dryRun: if not os.path.exists(pkgPath): os.makedirs(pkgPath) proc = subprocess.Popen(["git", "clone", "--branch", pkg["__BRANCH"], pkg["url"], pkg["name"]], cwd = prefixPath) if proc.wait() != 0: raise TransactionError("Couldn't clone package '{0}' with branch '{1}' from '{2}'" .format(pkg["name"], pkg["__BRANCH"], pkg["url"])) else: raise InvalidPackageError("Unsupported repository type of package '{0}': '{1}'" .format(pkg["name"], pkg["repoType"])) if dryRun: print("Dry run. Nothing was installed/updated.") if problemsOccurred: print("WARNING: problems were detected during dry installation run. See above.") return