From 35a3dde9f51b978b8ac8481b623d39cd6f79e842 Mon Sep 17 00:00:00 2001 From: Vladimir Testov Date: Wed, 7 Nov 2012 11:31:34 -0500 Subject: [PATCH] LOG - repograph: new option --tab-separated --- urpm-repograph.py | 588 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 415 insertions(+), 173 deletions(-) diff --git a/urpm-repograph.py b/urpm-repograph.py index bb58427..33dadb8 100755 --- a/urpm-repograph.py +++ b/urpm-repograph.py @@ -2,12 +2,12 @@ ''' " Repograph utility for outputting graph of packages and their dependencies " on each other. Also checks for unprovided dependencies. -" -" The tool downloads, unpacks and parses synthesis.hdlist.cz and +" +" The tool downloads, unpacks and parses synthesis.hdlist.cz and " (if necessary) files.xml.lzma to check for unprovided dependencies and " to output graph of packages and their dependencies in DOT language format. " The tool outputs data to standart output or to file. -" +" " REQUIREMENTS " ============ " - urpmi @@ -17,7 +17,7 @@ " - libxml2 python library " - rpm python library " - networkx python library -" +" " Copyright (C) 2012 ROSA Laboratory. " Written by Vladimir Testov " @@ -56,10 +56,6 @@ from rpm5utils.urpmgraphs.algorithms.cycles import simple_cycles import gettext gettext.install('urpm-tools') -#import rpm5utils.urpmgraphs -#from rpm5utils.urpmgraphs.algorithms import cycles -#from rpm5utils.urpmgraphs.classes import digraph - synthesis_arch = "synthesis.hdlist.cz" synthesis_arch_renamed = "synthesis.hdlist.gz" @@ -72,13 +68,16 @@ loopdotfile = "loopgraph" altdotfile = "altgraph" default_output = "sys.stdout" timeout = 5 +nodes_file = "nodes.txt" +edges_file = "edges.txt" +modedef = ['normal', 'cross-repo', 'broken'] re_search_unver = re.compile("([^\[\]]+)[\[\]]") re_search_verrel = re.compile("\[(== |> |< |>= |<= )([\{\}+=0-9a-zA-Z_\.]*:)?([[\{\}+=0-9a-zA-Z_\.]+)(-[[\{\}+=0-9a-zA-Z_\.]+)?([^\[\]]*)\]$") def ParseCommandLine(): """Parse arguments. - + Parse arguments from command line. Return these arguments. """ @@ -87,7 +86,7 @@ def ParseCommandLine(): parser.add_argument("repository", action="store", nargs=1, metavar="REPOSITORY", help="URL or local PATH to repository.") parser.add_argument("--cross", "-c", action="store", nargs='+', metavar="CROSS_REPO", - help=_("Search for cross-repository references in CROSS_REPO(s) repositories.")) + help=_("Search for cross-repository references in CROSS_REPO(s) repositories.")) parser.add_argument("--quiet", "-q", action="store_false", help=_("Hide service messages. (About progress status etc.)")) @@ -105,7 +104,7 @@ def ParseCommandLine(): help=_("Show unprovided dependencies.")) pkgrequiresgroup = parser.add_mutually_exclusive_group() - pkgrequiresgroup.add_argument("--requires-recursive", action="store", nargs=1, default=None, + pkgrequiresgroup.add_argument("--requires-recursive", action="store", nargs=1, default=None, metavar="PKG", help=_("Search for packages, which are required by package PKG (PKG is a file name or package name)")) pkgrequiresgroup.add_argument("--whatrequires", action="store", nargs=1, default=None, metavar="PKG", help=_("Search for packages, which requires package PKG (PKG is a file name or package name)")) @@ -128,6 +127,10 @@ def ParseCommandLine(): graphgroup.add_argument("--nograph", "-n", action="store_true", help=_("Do not output graph. Tool will not start working if --quiet, --nograph are present \ and --verbose is not. (If there is nothing to output - then nothing has to be done.)")) + + parser.add_argument("--tab-separated", "-t", action="store_true", + help=_("Output in tab-separated format. If OUTPUT_FILE is not present, files \"" + nodes_file + "\" and \"" + edges_file + "\" \ + will be created in the current directory. Otherwise these files will be written to the selected directory.")) return parser.parse_args() def exit_proc(arg): @@ -139,8 +142,9 @@ def exit_proc(arg): err_loops = arg.loops err_alternatives = arg.alternatives err_different = arg.different - - if (err_output != None) and not ((err_loops or err_alternatives) and (err_different)): + err_iftab = arg.tab_separated + + if (err_output != None) and not ((err_loops or err_alternatives) and (err_different)) and not err_iftab: err_output.close() if os.path.isdir(err_tmp_dir): shutil.rmtree(err_tmp_dir) @@ -148,7 +152,7 @@ def exit_proc(arg): def CheckURL(url, arg): """URL check. - + Check that URL is gettable. """ try: @@ -159,7 +163,7 @@ def CheckURL(url, arg): def CheckURLPATH(urlpath, arg): """Argument checks. - + Check, that url or path is correct. """ if (urlpath.startswith("http://") or urlpath.startswith("ftp://")): @@ -192,7 +196,7 @@ def CheckURLPATH(urlpath, arg): def CheckOptions(arg): """Options check. - + Make options understandable for the program. """ if (arg.suggests == 0): @@ -200,17 +204,32 @@ def CheckOptions(arg): def CheckOutput(arg): """Check output file. - + Check if the file can be created and redirect standart output to this file. """ file_output = arg.output ifloops = arg.loops ifalternatives = arg.alternatives ifdifferent = arg.different + iftab = arg.tab_separated if (file_output == "sys.stdout") or (file_output == "stdout"): - arg.output = sys.stdout - return + if iftab: + if ifdifferent: + if ifalternatives: + arg.output = './' + altdotfile + '/' + elif ifloops: + arg.output = './' + loopdotfile + '/' + else: + arg.output = './' + file_output = arg.output + else: + arg.output = sys.stdout + return + else: + if iftab: + arg.output = './' + file_output + '/' + file_output = arg.output if((ifloops or ifalternatives) and ifdifferent): # check for dir if(os.path.isdir(file_output)): print _("Error: directory %s already exists") % file_output @@ -222,7 +241,7 @@ def CheckOutput(arg): print _("Error: File %s already exists") % file_output arg.output = None exit_proc(arg) - + try: os.makedirs(file_output) except: @@ -233,6 +252,22 @@ def CheckOutput(arg): file_output = file_output + '/' arg.output = file_output else: + if iftab: + if os.path.isfile(file_output + nodes_file): + print _("Error: File %s already exists") % (file_output + nodes_file) + arg.output = None + exit_proc(arg) + if os.path.isfile(file_output + edges_file): + print _("Error: File %s already exists") % (file_output + edges_file) + arg.output = None + exit_proc(arg) + try: + os.makedirs(file_output) + except: + print _("Error: directory %s was not created") % file_output + arg.output = None + exit_proc(arg) + return if(os.path.isfile(file_output)): print _("Error: File %s already exists") % file_output arg.output = None @@ -255,7 +290,7 @@ def GetFile(urlpath, filename, localdir, arg): """Donwload archive. """ ifnotquiet = arg.quiet - + if not os.path.isdir(localdir): os.makedirs(os.path.realpath(localdir)) if ifnotquiet: @@ -279,11 +314,11 @@ def GetFile(urlpath, filename, localdir, arg): def RenameSynthFile(localdir, arg): """Rename. - + Rename Synthesis file so zgip can understand format. """ ifnotquiet = arg.quiet - + if not os.path.isfile(localdir + synthesis_arch): print _("Error: file not found: ") + localdir + synthesis_arch exit_proc(arg) @@ -291,7 +326,7 @@ def RenameSynthFile(localdir, arg): os.rename(localdir + synthesis_arch, localdir + synthesis_arch_renamed) except OSError: print _("Error: cannot rename file %(from)s to %(to)s") % {"from": synthesis_arch, "to": synthesis_arch_renamed} - + exit_proc(arg) if not os.path.isfile(localdir + synthesis_arch_renamed): print _("Error: file %s is missing.") % (localdir + synthesis_arch_renamed) @@ -302,11 +337,11 @@ def RenameSynthFile(localdir, arg): def UnpackSynthFile(localdir, arg): """Unpack Synthesis file. - + Unpack renamed synthesis file using gzip. """ ifnotquiet = arg.quiet - + if ifnotquiet: print _("unpacking file ") + synthesis_arch_renamed if not os.path.isfile(localdir + synthesis_arch_renamed): @@ -319,10 +354,10 @@ def PrepareSynthFile(localdir, arg): """ RenameSynthFile(localdir, arg) UnpackSynthFile(localdir, arg) - + def ParseVersion(names_list): """Parse version info if present. - + Parse version information from the field. e.g. provided_name[>= 1.2.3-4.5.6] is parsed to (provided_name, sign, (epoch, version, release)) """ @@ -372,27 +407,31 @@ def TagEpoch(i): def RPMNameFilter(rpmname, disttagepoch): """Parse name and verrel. - + Function that parses name, version and release of a package. """ string = rpmname.split('-') lastpart = string.pop() tmp = lastpart.split('.') - tmp.pop() + issrc = (tmp.pop() == "src") + ismageia = 0 + if tmp[-1].startswith("mga"): + tmp.pop() + ismageia = 1 lastpart = '.'.join(tmp) if (lastpart[0].isdigit() or (not lastpart.startswith(disttagepoch))) and\ - (not lastpart.isdigit()): + ((not lastpart.isdigit()) or issrc or ismageia): name = '-'.join(string[:-1]) else: name = '-'.join(string[:-2]) - return name + return name def ParseSynthFile(dict_provides, dict_asks, localdir, arg): """Collect packages information. - + Parse synthesis.hdlist file. dict_provides[phrase]=[(name, sign, verrel)] contain names of packages providing phrase - dict_asks[pkg_name]=[(name, sign, verrel)] contain everything + dict_asks[pkg_name]=[(name, sign, verrel)] contain everything that pkg_name package asks """ ifnotquiet = arg.quiet @@ -401,9 +440,9 @@ def ParseSynthFile(dict_provides, dict_asks, localdir, arg): ifverbose = arg.verbose iftagepoch = arg.requires_recursive or arg.whatrequires ifnothide = not iftagepoch - + if not os.path.isfile(localdir + synthesis_file): - print _("Error: Synthesis file %s was not found.") % (localdir + synthesis_file) + print _("Error: Synthesis file %s was not found.") % (localdir + synthesis_file) exit_proc(-1) if ifnotquiet: print _("Parsing synthesis.") @@ -428,7 +467,7 @@ def ParseSynthFile(dict_provides, dict_asks, localdir, arg): tmp[0] = tmp[0][0] else: tmp[0] = tmpline[2] - + parsed_tmp = ParseVersion(tmp[3]) for (phrase, sign, verrel) in parsed_tmp: if ((ifverbose and ifnothide) and (sign != '==') and (sign != '')): @@ -454,7 +493,7 @@ def ParseSynthFile(dict_provides, dict_asks, localdir, arg): def compare_verrel(verrel1, sign, verrel2): """Compare versions. - + Compare versions with attention to sign. """ (e1, v1, r1) = verrel1 @@ -489,7 +528,7 @@ def compare_verrel(verrel1, sign, verrel2): def compare_2signs_verrel(provide_verrel, provide_sign, verrel, sign): """Compare versions. - + Compare versions with attention to two signs. """ (e1, v1, r1) = provide_verrel @@ -514,10 +553,10 @@ def compare_2signs_verrel(provide_verrel, provide_sign, verrel, sign): if ((provide_sign == '>') or (provide_sign == '>=')) and (compare == -1): return 1 return 0 - + def print_verrel(verrel): """Output version info. - + Formatted output of version info. """ (e, v, r) = verrel @@ -529,14 +568,14 @@ def print_verrel(verrel): if (r != ''): result = result + '-' + r return result - + def unpack_fileslist(localdir, arg): """Unpack files.xml file. - + Unpack files.xml.lzma using lzma. """ ifnotquiet = arg.quiet - + if ifnotquiet: print _("unpacking file ") + fileslist_arch if not os.path.isfile(localdir + fileslist_arch): @@ -550,7 +589,7 @@ def parse_fileslist(filename_check, filename_found, count_depend, dict_depend, l ifnotquiet = arg.quiet ifverbose = arg.verbose ifnothide = (not arg.requires_recursive) and (not arg.whatrequires) - + if ifnotquiet: print _("Reading fileslist") if not os.path.isfile(localdir + fileslist_file): @@ -570,7 +609,7 @@ def parse_fileslist(filename_check, filename_found, count_depend, dict_depend, l if(tag_package.name != "files"): tag_package = tag_package.next continue - + tag_property = tag_package.properties while(tag_property) and (tag_property.name != "fn"): tag_property = tag_property.next @@ -614,10 +653,10 @@ def parse_fileslist(filename_check, filename_found, count_depend, dict_depend, l tag_package = tag_package.next doc.freeDoc() #found!!! update count_depend dict_depend add to filename_found - + def process_fileslist(filename_check, filename_found, count_depend, dict_depend, localdir, ifcry, arg): """Process files.xml. - + Make necessary steps to process files.xml. """ if (ifcry == None): @@ -628,10 +667,10 @@ def process_fileslist(filename_check, filename_found, count_depend, dict_depend, GetFile(path, fileslist_arch, localdir, arg) unpack_fileslist(localdir, arg) parse_fileslist(filename_check, filename_found, count_depend, dict_depend, localdir, ifcry, arg) - + def remake_count_depend(count_depend): """Build count_depend. - + Build count_depend in case of using --file option. """ result = {} @@ -645,7 +684,7 @@ def remake_count_depend(count_depend): def AddDepend(provides, temp_dict, packagename, asked, mode, dict_cross_error, ifshow): """Add dependency to temp dictionary. - + Used in FillDepend function. """ if (provides not in temp_dict) and (provides != packagename): @@ -661,11 +700,11 @@ def AddDepend(provides, temp_dict, packagename, asked, mode, dict_cross_error, i if (ifshow): print _("Warning: package has self-dependecies: ") + packagename +\ "\n <" + asked + ">" - -def FillDepend(dict_tmp_provides, asked, temp_dict, packagename, sign, verrel, + +def FillDepend(dict_tmp_provides, asked, temp_dict, packagename, sign, verrel, dict_error, dict_cross_error, mode, ifshow, ifshowunprovided): """Fill dependency dictionary. - + Used in FindDepend function. """ found = 0 @@ -696,7 +735,7 @@ def FillDepend(dict_tmp_provides, asked, temp_dict, packagename, sign, verrel, def generate_error_dict(filename_check, filename_found, dict_error, dict_depend, count_depend, ifshow, ifshowunprovided): """Generate Warnings about unprovided packages. - + Used in FindDepend function. """ for filename in filename_check: @@ -719,7 +758,7 @@ def generate_error_dict(filename_check, filename_found, dict_error, dict_depend, def FindDepend(dict_provides, dict_asks, dict_cross_provides, dict_cross_asks, arg): """Find dependencies. - + Find dependencies and tell about unprovided packages. """ ifnotquiet = arg.quiet @@ -729,7 +768,7 @@ def FindDepend(dict_provides, dict_asks, dict_cross_provides, dict_cross_asks, a ifnothide = (not arg.requires_recursive) and (not arg.whatrequires) ifshow = ifverbose and ifnothide ifshowunprovided = arg.unprovided or arg.broken - + dict_error = {} dict_cross_error = {} dict_depend = {} @@ -784,7 +823,7 @@ def FindDepend(dict_provides, dict_asks, dict_cross_provides, dict_cross_asks, a if (asked not in filename_check): filename_check[asked] = {} filename_check[asked][packagename] = 1 # from cross-repo - + if packagename not in dict_depend: dict_depend[packagename] = temp_dict else: @@ -798,7 +837,7 @@ def FindDepend(dict_provides, dict_asks, dict_cross_provides, dict_cross_asks, a count_depend[length] = count_depend[length] + 1 else: count_depend[packagename] = len(temp_dict) - + if ifcheckfiles: process_fileslist(filename_check, filename_found, count_depend, dict_depend, arg.tmp_dir, None, arg) if ifcross: @@ -820,15 +859,19 @@ def FindDepend(dict_provides, dict_asks, dict_cross_provides, dict_cross_asks, a def AssignColors(dict_depend, count_depend, arg): """Assign colors. - + Assign colors for graph output. """ ifnotquiet = arg.quiet ifchangecolors = arg.whatrequires - + iftab = arg.tab_separated + dict_colors = {} dict_count = {} - + + if iftab: + return dict_colors + if ifnotquiet: print _("Calculating colors.") sorted_count = sorted(count_depend) @@ -854,20 +897,20 @@ def AssignColors(dict_depend, count_depend, arg): def OutputGraphHead(file_output): """Output Graph head. - + Static information about graph. """ file_output.write('\n\ndigraph packages {\nsize="20.69,25.52";\nratio="fill";\n' +\ 'rankdir="TB";\nnode[style="filled"];\nnode[shape="box"];\n\n') - + def print_color(color_tuple): """Format color. - + Format color for outputting. """ return str(color_tuple[0]) + ' ' + str(color_tuple[1]) + ' ' +\ str(color_tuple[2]) - + def OutputGraphLoopBody(loop, loop_color, file_output): """Output Graph body in --loop case. """ @@ -889,10 +932,10 @@ def OutputGraphAltBody(phrase, alt, alt_color, file_output): tmp_string = tmp_string + '"' + packagename + '"\n' tmp_string = tmp_string + '} [color="' + str(alt_color) + ' 1.0 1.0"];\n\n' file_output.write(tmp_string) - + def OutputGraphBody(some_list, dict_color, file_output, packagename, node_type): """Output Graph body. - + Output Graph. """ tmp_string = '"' + packagename + '" -> {\n' @@ -912,51 +955,117 @@ def OutputGraphBody(some_list, dict_color, file_output, packagename, node_type): elif (node_type == 2): tmp_string = tmp_string + '};\n\n' file_output.write(tmp_string) - - + def OutputGraphTail(file_output): """Finish the graph. """ file_output.write('}\n') - + +def GetNodesEdges(dict_depend): + nodes = {} + edges = [] + for packagename in dict_depend: + if packagename not in nodes: + nodes[packagename] = 0 + for pkg in dict_depend[packagename]: + if pkg not in nodes: + nodes[pkg] = 0 + mode = dict_depend[packagename][pkg] + edges.append([packagename, pkg, mode]) + if mode == 2: + nodes[pkg] = 2 + return (nodes, edges) + +def OutputNodes(dict_depend, nodes, arg): + """Output nodes. + """ + output_dir = arg.output + file_output = output_dir + nodes_file + if os.path.isfile(file_output): + print _("Error: File %s already exists") % file_output + arg.output = None + exit_proc(arg) + sorted_list = sorted(nodes) + try: + NODES = open(file_output, "w") + except: + print _("Error: File %s cannot be created") % file_output + arg.output = None + exit_proc(arg) + + for pkg in sorted_list: + NODES.write('\t'.join([pkg, modedef[nodes[pkg]]])) + NODES.write('\n') + + NODES.close() + +def OutputEdges(dict_depend, edges, arg): + """Output edges. + """ + output_dir = arg.output + file_output = output_dir + edges_file + if os.path.isfile(file_output): + print _("Error: File %s already exists") % file_output + arg.output = None + exit_proc(arg) + try: + EDGES = open(file_output, "w") + except: + print _("Error: File %s cannot be created") % file_output + arg.output = None + exit_proc(arg) + + for (node1, node2, mode) in edges: + EDGES.write('\t'.join([node1, node2, modedef[mode]])) + EDGES.write('\n') + + EDGES.close() + def OutputGraph(dict_depend, dict_color, arg): """Output the graph. """ file_output = arg.output + iftab = arg.tab_separated if arg.whatrequires: selected_node = arg.whatrequires[0] elif arg.requires_recursive: selected_node = arg.requires_recursive[0] else: selected_node = None - OutputGraphHead(file_output) - if (selected_node): - file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') - sorted_list = sorted(dict_depend) - for packagename in sorted_list: - if not dict_depend[packagename]: - continue - usual_list = [] - cross_list = [] - missed_list = [] - for pkg in dict_depend[packagename]: - mode = dict_depend[packagename][pkg] - if (mode == 0): - usual_list.append(pkg) - elif (mode == 1): - cross_list.append(pkg) - elif (mode == 2): - missed_list.append(pkg) - - if (len(usual_list) > 0): - OutputGraphBody(usual_list, dict_color, file_output, packagename, 0) - if (len(cross_list) > 0): - OutputGraphBody(cross_list, dict_color, file_output, packagename, 1) - if (len(missed_list) > 0): - OutputGraphBody(missed_list, None, file_output, packagename, 2) - - OutputGraphTail(file_output) + if not iftab: + OutputGraphHead(file_output) + + if (selected_node): + file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') + sorted_list = sorted(dict_depend) + for packagename in sorted_list: + if not dict_depend[packagename]: + continue + usual_list = [] + cross_list = [] + missed_list = [] + for pkg in dict_depend[packagename]: + mode = dict_depend[packagename][pkg] + if (mode == 0): + usual_list.append(pkg) + elif (mode == 1): + cross_list.append(pkg) + elif (mode == 2): + missed_list.append(pkg) + + if (len(usual_list) > 0): + OutputGraphBody(usual_list, dict_color, file_output, packagename, 0) + if (len(cross_list) > 0): + OutputGraphBody(cross_list, dict_color, file_output, packagename, 1) + if (len(missed_list) > 0): + OutputGraphBody(missed_list, None, file_output, packagename, 2) + + OutputGraphTail(file_output) + else: #iftab == TRUE + (nodes, edges) = GetNodesEdges(dict_depend) + OutputNodes(dict_depend, nodes, arg) + OutputEdges(dict_depend, edges, arg) def CountPor(number): tmp = number / 10 @@ -973,78 +1082,210 @@ def LeadingZeroes(number, por): def OutputLoopGraph(loops, colors, arg): """Output graph(s) of loops. """ + iftab = arg.tab_separated ifdifferent = arg.different - if arg.whatrequires: - selected_node = arg.whatrequires[0] - elif arg.requires_recursive: - selected_node = arg.requires_recursive[0] - else: - selected_node = None - output = arg.output - file_output = output - if not ifdifferent: - OutputGraphHead(file_output) - if (selected_node): - file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') + if not iftab: + if arg.whatrequires: + selected_node = arg.whatrequires[0] + elif arg.requires_recursive: + selected_node = arg.requires_recursive[0] + else: + selected_node = None - length = len(colors) - por = CountPor(length) - for i in range(length): - if ifdifferent: - filename = output + loopdotfile + LeadingZeroes(i, por) + '.dot' - file_output = open(filename, 'w') + output = arg.output + file_output = output + if not ifdifferent: OutputGraphHead(file_output) if (selected_node): file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') - OutputGraphLoopBody(loops[i], colors[i], file_output) - if ifdifferent: - OutputGraphTail(file_output) - file_output.close() - if not ifdifferent: - OutputGraphTail(file_output) + length = len(colors) + por = CountPor(length) + for i in range(length): + if ifdifferent: + filename = output + loopdotfile + LeadingZeroes(i, por) + '.dot' + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + OutputGraphHead(file_output) + if (selected_node): + file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') + OutputGraphLoopBody(loops[i], colors[i], file_output) + if ifdifferent: + OutputGraphTail(file_output) + file_output.close() + + if not ifdifferent: + OutputGraphTail(file_output) + else: #tab-separated + output = arg.output + if not ifdifferent: + filename = output + edges_file + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + length = len(loops) + pot = CountPor(length) + nodes = [] + i = 0 + for loop in loops: + if ifdifferent: + dirname = output + loopdotfile + LeadingZeroes(i, pot) + '/' + filename = dirname + edges_file + try: + os.makedirs(dirname) + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + nodes = [] + j = 0 + for pkg in loop: + if j == 0: + j = 1 + file_output.write(str(pkg)) + else: + file_output.write('\t' + str(pkg)) + if pkg not in nodes: + nodes.append(pkg) + file_output.write('\n') + if ifdifferent: + file_output.close() + filename = dirname + nodes_file + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + for pkg in nodes: + file_output.write(str(pkg) + '\n') + file_output.close() + i = i + 1 + if not ifdifferent: + filename = output + nodes_file + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + for pkg in nodes: + file_output.write(str(pkg) + '\n') + file_output.close() def OutputAltGraph(alternatives, colors, arg): """Output graph(s) of alternatives. """ + iftab = arg.tab_separated ifdifferent = arg.different - if arg.whatrequires: - selected_node = arg.whatrequires[0] - elif arg.requires_recursive: - selected_node = arg.requires_recursive[0] - else: - selected_node = None - output = arg.output - file_output = output - if not ifdifferent: - OutputGraphHead(file_output) - if (selected_node): - file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') + if not iftab: + if arg.whatrequires: + selected_node = arg.whatrequires[0] + elif arg.requires_recursive: + selected_node = arg.requires_recursive[0] + else: + selected_node = None - i = 0 - length = len(colors) - por = CountPor(length) - for phrase in alternatives: - if ifdifferent: - filename = output + altdotfile + LeadingZeroes(i, por) + '.dot' - file_output = open(filename, 'w') + output = arg.output + file_output = output + if not ifdifferent: OutputGraphHead(file_output) if (selected_node): file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') - OutputGraphAltBody(phrase, alternatives[phrase], colors[i], file_output) - if ifdifferent: - OutputGraphTail(file_output) - file_output.close() - i = i + 1 - if not ifdifferent: - OutputGraphTail(file_output) + i = 0 + length = len(colors) + por = CountPor(length) + for phrase in alternatives: + if ifdifferent: + filename = output + altdotfile + LeadingZeroes(i, por) + '.dot' + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + OutputGraphHead(file_output) + if (selected_node): + file_output.write('"' + selected_node + '" [color="0.4 1.0 1.0"];\n') + OutputGraphAltBody(phrase, alternatives[phrase], colors[i], file_output) + if ifdifferent: + OutputGraphTail(file_output) + file_output.close() + i = i + 1 + + if not ifdifferent: + OutputGraphTail(file_output) + else: #tab-separated + output = arg.output + if not ifdifferent: + filename = output + edges_file + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + length = len(alternatives) + pot = CountPor(length) + nodes = [] + i = 0 + for phrase in alternatives: + if ifdifferent: + dirname = output + altdotfile + LeadingZeroes(i, pot) + '/' + filename = dirname + edges_file + try: + os.makedirs(dirname) + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + nodes = [] + file_output.write(str(phrase)) + for pkg in alternatives[phrase]: + file_output.write('\t' + str(pkg)) + if pkg not in nodes: + nodes.append(pkg) + file_output.write('\n') + if ifdifferent: + file_output.close() + filename = dirname + nodes_file + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + for pkg in nodes: + file_output.write(str(pkg) + '\n') + file_output.close() + i = i + 1 + if not ifdifferent: + filename = output + nodes_file + try: + file_output = open(filename, 'w') + except: + print _("Error: file %s cannot be created") % filename + arg.output = None + exit_proc(arg) + for pkg in nodes: + file_output.write(str(pkg) + '\n') + file_output.close() def BuildGraph(dict_depend): """Build additional structures. - + Build structures used in algorithm that finds loops. And later in --pkg-... options. """ dict_out = {} @@ -1058,10 +1299,10 @@ def BuildGraph(dict_depend): dict_out[pkg2].append(packagename) dict_in[packagename].append(pkg2) return (dict_in, dict_out) - + def RemoveNonCycle(dict_in, dict_out, arg): """Remove non-cycle nodes from graph. - + Remove all nodes that are not present in any loop. Linear algorithm. On each step it checks all marked nodes. If node hasn't got any nodes dependent from it or it's not @@ -1071,7 +1312,7 @@ def RemoveNonCycle(dict_in, dict_out, arg): All remained nodes are included in some loop. """ ifnotquiet = arg.quiet - + check = [] #items for further checks to_remove = [] #items for remove for pkg in dict_in: @@ -1114,14 +1355,14 @@ def RemoveNonCycle(dict_in, dict_out, arg): def FindLoops(dict_depend, arg): """Find all simple loops in oriented graph. - + First, remove all nodes, that are not present in any loop. Then search for all loops in what has remained. """ ifnotquiet = arg.quiet ifverbose = arg.verbose file_output = arg.output - + benchtime = time.clock() (dict_in, dict_out) = BuildGraph(dict_depend) RemoveNonCycle(dict_in, dict_out, arg) @@ -1158,12 +1399,12 @@ def FindLoops(dict_depend, arg): def FindAlternatives(dict_provides, arg): """Find Alternatives. - + Select all phrases that are provided by more than one package. """ ifverbose = arg.verbose ifnotquiet = arg.quiet - + if (ifnotquiet): print _("Searching alternatives.") altlist = {} @@ -1172,7 +1413,7 @@ def FindAlternatives(dict_provides, arg): altlist[phrase] = [] for (packagename, r1, r2) in dict_provides[phrase]: altlist[phrase].append(packagename) - + if ifverbose: length = len(altlist) i = 1 @@ -1183,14 +1424,14 @@ def FindAlternatives(dict_provides, arg): for packagename in altlist[phrase]: print " -> " + packagename i = i + 1 - + if (ifnotquiet): print _("End of search.") return altlist def FindBroken(dict_depend, count_depend, dict_asks, dict_provides, dict_cross_asks, dict_cross_provides, arg): """Find Broken packages. - + Select all unprovided packages (with unprovided dependencies or dependent from packages with unprovided dependencies. """ startlist = [] @@ -1209,7 +1450,7 @@ def AssignDictColors(tmpdict): for i in range(length): colors.append ((i * 1.) / length) return colors - + def get_temp(i, arg): """Get numbered temporarily directory name. """ @@ -1217,7 +1458,7 @@ def get_temp(i, arg): def PkgCheck(pkgname, dict_asks, dict_cross_asks): """Check that PKG from --pkg-require or --pkg-provide is existent in repository. - + Searches PKG in file names and package names from repository. """ if pkgname in dict_asks: @@ -1226,7 +1467,7 @@ def PkgCheck(pkgname, dict_asks, dict_cross_asks): for filename in dict_asks: if (pkgname == dict_asks[filename][1]): return filename - + if pkgname in dict_cross_asks: return pkgname else: @@ -1242,7 +1483,7 @@ def RemakeAsks(startlist, dict_asks, dict_depend, dict_cross_asks, arg, ifbroken ifrequires_recursive = arg.requires_recursive ifnotquite = arg.quiet ifverbose = arg.verbose - + (dict_in, dict_out) = BuildGraph(dict_depend) if (ifbroken != None): dict_tmp = dict_out @@ -1276,7 +1517,7 @@ def RemakeAsks(startlist, dict_asks, dict_depend, dict_cross_asks, arg, ifbroken print _("Level %d dependency.") % level_cnt for tmppkg in list_append: print " -> " + tmppkg - + ischanged = 0 tmp_append = [] #check for every filename in custody if it in list_selected. @@ -1327,7 +1568,7 @@ def RemoveExternal(dict_asks, dict_provides, dict_cross_asks, dict_cross_provide new_dict_asks[filename][0].append(asks) elif ifshow: new_dict_asks[filename][0].append(asks) - + for filename in dict_cross_asks: for asks in dict_cross_asks[filename][0]: if asks[0] in dict_provides: @@ -1337,12 +1578,12 @@ def RemoveExternal(dict_asks, dict_provides, dict_cross_asks, dict_cross_provide new_dict_provides[asks[0]] = [] if not pkg in new_dict_provides[asks[0]]: new_dict_provides[asks[0]].append(pkg) - + return (new_dict_asks, new_dict_provides) def RemakeDicts(dict_depend, count_depend, dict_asks, dict_provides, dict_cross_asks, dict_cross_provides, arg, brokenlist=None): """Procedure for rebuilding packages lists. - + for --whatrequires and --requires-recursive options and for --broken option """ @@ -1350,7 +1591,7 @@ def RemakeDicts(dict_depend, count_depend, dict_asks, dict_provides, dict_cross_ whatrequires = arg.whatrequires requires_recursive = arg.requires_recursive ifshow = arg.unprovided or arg.broken - + if (ifnotquiet): print _("Remaking structures.") if (brokenlist == None): @@ -1389,14 +1630,15 @@ def main(args): ifbroken = arg.broken ifoptact = ifloops or ifalternatives or ifbroken ifunprovided = arg.unprovided - + iftab = arg.tab_separated + arg.crossurl = [] arg.tmp_dir = "" if (arg.output): file_output = arg.output[0] else: file_output = default_output - arg.output = None + arg.output = file_output if (not ifnotquiet) and (not ifverbose) and (ifnograph): print _("Do not use -q/--quiet and -n/--nograph without -v/--verbose together.") print _("That way there is no information to output anywhere. Nothing will be done.") @@ -1412,6 +1654,8 @@ def main(args): for i in crossrange: arg.crossurl.append(CheckURLPATH(arg.cross[i], arg)) CheckOptions(arg) + CheckOutput(arg) + arg.tmp_dir = tempfile.mkdtemp() + '/' #get all needed files GetFile(arg.repository, synthesis_arch, arg.tmp_dir, arg) @@ -1439,8 +1683,6 @@ def main(args): if (answer): (dict_depend, count_depend, dict_asks, dict_provides, dict_cross_asks, dict_cross_provides) = answer - arg.output = file_output - CheckOutput(arg) if (ifoptact): ##REMAKE (MUTUALLY EXCLUSIVE) if (ifloops): loops = FindLoops(dict_depend, arg) @@ -1465,7 +1707,7 @@ def main(args): exit_proc(arg) dict_color = AssignColors(dict_depend, count_depend, arg) OutputGraph(dict_depend, dict_color, arg) - + exit_proc(arg) if __name__ == "__main__":