| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 import copy | |
| 7 import optparse | |
| 8 | |
| 9 __version__ = "1.0" | |
| 10 | |
| 11 # Constants used by Visual Studio. | |
| 12 UNKNOWN_GUID = "{00000000-0000-0000-0000-000000000000}" | |
| 13 FOLDER_GUID = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}" | |
| 14 C_PROJECT_GUID = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}" | |
| 15 CSHARP_PROJECT_GUID = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}" | |
| 16 | |
| 17 # A project defines it name, its guid and its dependencies. | |
| 18 class Project: | |
| 19 def __init__(self): | |
| 20 self.name = "" | |
| 21 self.type = UNKNOWN_GUID | |
| 22 self.deps = [] | |
| 23 | |
| 24 def __str__(self): | |
| 25 return self.name | |
| 26 | |
| 27 | |
| 28 def ScanSlnFile(filename): | |
| 29 """Scan a Visual Studio .sln and extract the project dependencies.""" | |
| 30 try: | |
| 31 sln = open(filename, "r") | |
| 32 except IOError: | |
| 33 sys.stderr.write("Unable to open " + filename + " for reading.\n") | |
| 34 return 1 | |
| 35 projects = {} | |
| 36 project = None | |
| 37 while 1: | |
| 38 line = sln.readline().strip() | |
| 39 if not line: | |
| 40 break | |
| 41 | |
| 42 if line.startswith('Project("{'): | |
| 43 # Project definition line looks like | |
| 44 # Project("$TypeGuid") = "$ProjectName", "$ProjectPath", "$ProjectGuid"$ | |
| 45 items = line.split('"') | |
| 46 project = Project() | |
| 47 project.name = items[3] | |
| 48 project.path = items[5] | |
| 49 project.guid = items[7] | |
| 50 project.type = items[1] | |
| 51 projects[items[7]] = project | |
| 52 | |
| 53 # Start of a dependency group. | |
| 54 if line == "ProjectSection(ProjectDependencies) = postProject": | |
| 55 line = sln.readline().strip() | |
| 56 # End of a dependency group. | |
| 57 while line and line != "EndProjectSection": | |
| 58 project.deps.append(line[:len(project.guid)]) | |
| 59 line = sln.readline().strip() | |
| 60 | |
| 61 # We are done parsing. | |
| 62 sln.close() | |
| 63 return projects | |
| 64 | |
| 65 | |
| 66 def sln_deps(filename, project_to_scan, reverse): | |
| 67 """Displays the project's dependencies.""" | |
| 68 project_to_scan = project_to_scan.lower() | |
| 69 | |
| 70 projects = ScanSlnFile(filename) | |
| 71 | |
| 72 if reverse: | |
| 73 # Inverse the dependencies map so they are displayed in the reverse order. | |
| 74 # First, create a copy of the map. | |
| 75 projects_reversed = copy.deepcopy(projects) | |
| 76 for project_reversed in projects_reversed.itervalues(): | |
| 77 project_reversed.deps = [] | |
| 78 # Then, assign reverse dependencies. | |
| 79 for project in projects.itervalues(): | |
| 80 for dep in project.deps: | |
| 81 projects_reversed[dep].deps.append(project.guid) | |
| 82 projects = projects_reversed | |
| 83 | |
| 84 # Print the results. | |
| 85 for project in projects.itervalues(): | |
| 86 if project.type == FOLDER_GUID: | |
| 87 continue | |
| 88 if project_to_scan and project.name.lower() != project_to_scan: | |
| 89 continue | |
| 90 print project.name | |
| 91 deps_name = [projects[d].name for d in project.deps] | |
| 92 print "\n".join(str(" " + name) for name in sorted(deps_name, | |
| 93 key=str.lower)) | |
| 94 return 0 | |
| 95 | |
| 96 | |
| 97 def main(): | |
| 98 usage = "usage: %prog [options] solution [project]" | |
| 99 | |
| 100 description = ("Display the dependencies of a project in human readable" | |
| 101 " form. [project] is optional. If omited, all projects are" | |
| 102 " listed.") | |
| 103 | |
| 104 option_parser = optparse.OptionParser(usage = usage, | |
| 105 version="%prog " + __version__, | |
| 106 description = description) | |
| 107 option_parser.add_option("-r", | |
| 108 "--reverse", | |
| 109 dest="reverse", | |
| 110 action="store_true", | |
| 111 default=False, | |
| 112 help="Display the reverse dependencies") | |
| 113 options, args = option_parser.parse_args() | |
| 114 if len(args) != 1 and len(args) != 2: | |
| 115 option_parser.error("incorrect number of arguments") | |
| 116 | |
| 117 project_to_scan = "" | |
| 118 if len(args) == 2: | |
| 119 project_to_scan = args[1] | |
| 120 return sln_deps(args[0], project_to_scan, options.reverse) | |
| 121 | |
| 122 | |
| 123 if __name__ == '__main__': | |
| 124 sys.exit(main()) | |
| OLD | NEW |