bulkstamp.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #
  2. # bulkstamp.py:
  3. # Stamp versions on all files that can be found in a given tree.
  4. #
  5. # USAGE: python bulkstamp.py <version> <root directory> <descriptions>
  6. #
  7. # Example: python bulkstamp.py 103 ..\win32\Build\ desc.txt
  8. #
  9. # <version> corresponds to the build number. It will be concatenated with
  10. # the major and minor version numbers found in the description file.
  11. #
  12. # Description information is pulled from an input text file with lines of
  13. # the form:
  14. #
  15. # <basename> <white space> <description>
  16. #
  17. # For example:
  18. #
  19. # PyWinTypes.dll Common types for Python on Win32
  20. # etc
  21. #
  22. # The product's name, major, and minor versions are specified as:
  23. #
  24. # name <white space> <value>
  25. # major <white space> <value>
  26. # minor <white space> <value>
  27. #
  28. # The tags are case-sensitive.
  29. #
  30. # Any line beginning with "#" will be ignored. Empty lines are okay.
  31. #
  32. import sys
  33. import os
  34. import verstamp
  35. import fnmatch
  36. import win32api
  37. numStamped = 0
  38. g_patterns = [
  39. '*.dll',
  40. '*.pyd',
  41. '*.exe',
  42. '*.ocx',
  43. ]
  44. def walk(arg, dirname, names):
  45. global numStamped
  46. vars, debug, descriptions = arg
  47. for name in names:
  48. for pat in g_patterns:
  49. if fnmatch.fnmatch(name, pat):
  50. # Handle the "_d" thing.
  51. pathname = os.path.join(dirname, name)
  52. base, ext = os.path.splitext(name)
  53. if base[-2:]=='_d':
  54. name = base[:-2] + ext
  55. is_dll = ext.lower() != ".exe"
  56. if os.path.normcase(name) in descriptions:
  57. desc = descriptions[os.path.normcase(name)]
  58. try:
  59. verstamp.stamp(vars, pathname, desc, is_dll=is_dll)
  60. numStamped = numStamped + 1
  61. except win32api.error as exc:
  62. print("Could not stamp", pathname, "Error", exc.winerror, "-", exc.strerror)
  63. else:
  64. print('WARNING: description not provided for:', name)
  65. # skip branding this - assume already branded or handled elsewhere
  66. # print "Stamped", pathname
  67. def load_descriptions(fname, vars):
  68. retvars = {}
  69. descriptions = { }
  70. lines = open(fname, 'r').readlines()
  71. for i in range(len(lines)):
  72. line = lines[i].strip()
  73. if line != '' and line[0] != '#':
  74. idx1 = line.find(' ')
  75. idx2 = line.find('\t')
  76. if idx1 == -1 or idx2 < idx1:
  77. idx1 = idx2
  78. if idx1 == -1:
  79. print('ERROR: bad syntax in description file at line %d.' % (i+1))
  80. sys.exit(1)
  81. key = line[:idx1]
  82. val = line[idx1:].strip()
  83. if key in vars:
  84. retvars[key] = val
  85. else:
  86. descriptions[key] = val
  87. if 'product' not in retvars:
  88. print('ERROR: description file is missing the product name.')
  89. sys.exit(1)
  90. if 'major' not in retvars:
  91. print('ERROR: description file is missing the major version number.')
  92. sys.exit(1)
  93. if 'minor' not in retvars:
  94. print('ERROR: description file is missing the minor version number.')
  95. sys.exit(1)
  96. return retvars, descriptions
  97. def scan(build, root, desc, **custom_vars ):
  98. global numStamped
  99. numStamped = 0
  100. try:
  101. build = int(build)
  102. except ValueError:
  103. print('ERROR: build number is not a number: %s' % build)
  104. sys.exit(1)
  105. debug = 0 ### maybe fix this one day
  106. varList = ['major', 'minor', 'sub', 'company', 'copyright', 'trademarks', 'product']
  107. vars, descriptions = load_descriptions(desc, varList)
  108. vars['build'] = build
  109. vars.update(custom_vars)
  110. arg = vars, debug, descriptions
  111. os.path.walk(root, walk, arg)
  112. print("Stamped %d files." % (numStamped))
  113. if __name__ == '__main__':
  114. if len(sys.argv) != 4:
  115. print("ERROR: incorrect invocation. See script's header comments.")
  116. sys.exit(1)
  117. scan(*tuple(sys.argv[1:]))