vssutil.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import win32con, string, traceback
  2. import win32com.client, win32com.client.gencache
  3. import pythoncom
  4. import time
  5. import os
  6. constants = win32com.client.constants
  7. win32com.client.gencache.EnsureModule('{783CD4E0-9D54-11CF-B8EE-00608CC9A71F}', 0, 5, 0)
  8. error = "vssutil error"
  9. def GetSS():
  10. ss=win32com.client.Dispatch("SourceSafe")
  11. # SS seems a bit weird. It defaults the arguments as empty strings, but
  12. # then complains when they are used - so we pass "Missing"
  13. ss.Open(pythoncom.Missing, pythoncom.Missing, pythoncom.Missing)
  14. return ss
  15. def test(projectName):
  16. ss=GetSS()
  17. project = ss.VSSItem(projectName)
  18. for item in project.GetVersions(constants.VSSFLAG_RECURSYES):
  19. print(item.VSSItem.Name, item.VersionNumber, item.Action)
  20. # item=i.Versions[0].VSSItem
  21. # for h in i.Versions:
  22. # print `h.Comment`, h.Action, h.VSSItem.Name
  23. def SubstituteInString(inString, evalEnv):
  24. substChar = "$"
  25. fields = string.split(inString, substChar)
  26. newFields = []
  27. for i in range(len(fields)):
  28. didSubst = 0
  29. strVal = fields[i]
  30. if i%2!=0:
  31. try:
  32. strVal = eval(strVal,evalEnv[0], evalEnv[1])
  33. newFields.append(strVal)
  34. didSubst = 1
  35. except:
  36. traceback.print_exc()
  37. print("Could not substitute", strVal)
  38. if not didSubst:
  39. newFields.append(strVal)
  40. return string.join(map(str, newFields), "")
  41. def SubstituteInFile(inName, outName, evalEnv):
  42. inFile = open(inName, "r")
  43. try:
  44. outFile = open(outName, "w")
  45. try:
  46. while 1:
  47. line = inFile.read()
  48. if not line: break
  49. outFile.write(SubstituteInString(line, evalEnv))
  50. finally:
  51. outFile.close()
  52. finally:
  53. inFile.close()
  54. def VssLog(project, linePrefix = "", noLabels = 5, maxItems=150):
  55. lines = []
  56. num = 0
  57. labelNum = 0
  58. for i in project.GetVersions(constants.VSSFLAG_RECURSYES):
  59. num = num + 1
  60. if num > maxItems : break
  61. commentDesc = itemDesc = ""
  62. if i.Action[:5]=="Added":
  63. continue
  64. if len(i.Label):
  65. labelNum = labelNum + 1
  66. itemDesc = i.Action
  67. else:
  68. itemDesc = i.VSSItem.Name
  69. if str(itemDesc[-4:])==".dsp":
  70. continue
  71. if i.Comment:
  72. commentDesc ="\n%s\t%s" % (linePrefix, i.Comment)
  73. lines.append("%s%s\t%s%s" % (linePrefix, time.asctime(time.localtime(int(i.Date))), itemDesc, commentDesc))
  74. if labelNum > noLabels:
  75. break
  76. return string.join(lines,"\n")
  77. def SubstituteVSSInFile(projectName, inName, outName):
  78. import win32api
  79. if win32api.GetFullPathName(inName)==win32api.GetFullPathName(outName):
  80. raise RuntimeError("The input and output filenames can not be the same")
  81. sourceSafe=GetSS()
  82. project = sourceSafe.VSSItem(projectName)
  83. # Find the last label
  84. label = None
  85. for version in project.Versions:
  86. if version.Label:
  87. break
  88. else:
  89. print("Couldnt find a label in the sourcesafe project!")
  90. return
  91. # Setup some local helpers for the conversion strings.
  92. vss_label = version.Label
  93. vss_date = time.asctime(time.localtime(int(version.Date)))
  94. now = time.asctime(time.localtime(time.time()))
  95. SubstituteInFile(inName, outName, (locals(),globals()))
  96. def CountCheckouts(item):
  97. num = 0
  98. if item.Type==constants.VSSITEM_PROJECT:
  99. for sub in item.Items:
  100. num = num + CountCheckouts(sub)
  101. else:
  102. if item.IsCheckedOut:
  103. num = num + 1
  104. return num
  105. def GetLastBuildNo(project):
  106. i = GetSS().VSSItem(project)
  107. # Find the last label
  108. lab = None
  109. for version in i.Versions:
  110. lab = str(version.Label)
  111. if lab: return lab
  112. return None
  113. def MakeNewBuildNo(project, buildDesc = None, auto=0, bRebrand = 0):
  114. if buildDesc is None: buildDesc = "Created by Python"
  115. ss = GetSS()
  116. i = ss.VSSItem(project)
  117. num = CountCheckouts(i)
  118. if num > 0:
  119. msg = "This project has %d items checked out\r\n\r\nDo you still want to continue?" % num
  120. import win32ui
  121. if win32ui.MessageBox(msg, project, win32con.MB_YESNO) != win32con.IDYES:
  122. return
  123. oldBuild = buildNo = GetLastBuildNo(project)
  124. if buildNo is None:
  125. buildNo = "1"
  126. oldBuild = "<None>"
  127. else:
  128. try:
  129. buildNo = string.atoi(buildNo)
  130. if not bRebrand: buildNo = buildNo + 1
  131. buildNo = str(buildNo)
  132. except ValueError:
  133. raise error("The previous label could not be incremented: %s" % (oldBuild))
  134. if not auto:
  135. from pywin.mfc import dialog
  136. buildNo = dialog.GetSimpleInput("Enter new build number", buildNo, "%s - Prev: %s" % (project, oldBuild))
  137. if buildNo is None: return
  138. i.Label(buildNo, "Build %s: %s" % (buildNo,buildDesc))
  139. if auto:
  140. print("Branded project %s with label %s" % (project, buildNo))
  141. return buildNo
  142. if __name__=='__main__':
  143. # UpdateWiseExeName("PyWiseTest.wse", "PyWiseTest-10.exe")
  144. # MakeVersion()
  145. # test(tp)
  146. # MakeNewBuildNo(tp)
  147. tp = "\\Python\\Python Win32 Extensions"
  148. SubstituteVSSInFile(tp, "d:\\src\\pythonex\\win32\\win32.txt", "d:\\temp\\win32.txt")