PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/couchjs/scons/sconsign.py

http://github.com/cloudant/bigcouch
Python | 513 lines | 420 code | 37 blank | 56 comment | 39 complexity | 54fa27451e4004cb4233544e9917f4df MD5 | raw file
Possible License(s): Apache-2.0
  1. #! /usr/bin/env python
  2. #
  3. # SCons - a Software Constructor
  4. #
  5. # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons Foundation
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining
  8. # a copy of this software and associated documentation files (the
  9. # "Software"), to deal in the Software without restriction, including
  10. # without limitation the rights to use, copy, modify, merge, publish,
  11. # distribute, sublicense, and/or sell copies of the Software, and to
  12. # permit persons to whom the Software is furnished to do so, subject to
  13. # the following conditions:
  14. #
  15. # The above copyright notice and this permission notice shall be included
  16. # in all copies or substantial portions of the Software.
  17. #
  18. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  19. # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20. # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  22. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. __revision__ = "src/script/sconsign.py 5134 2010/08/16 23:02:40 bdeegan"
  26. __version__ = "2.0.1"
  27. __build__ = "r5134"
  28. __buildsys__ = "cooldog"
  29. __date__ = "2010/08/16 23:02:40"
  30. __developer__ = "bdeegan"
  31. import os
  32. import sys
  33. import time
  34. ##############################################################################
  35. # BEGIN STANDARD SCons SCRIPT HEADER
  36. #
  37. # This is the cut-and-paste logic so that a self-contained script can
  38. # interoperate correctly with different SCons versions and installation
  39. # locations for the engine. If you modify anything in this section, you
  40. # should also change other scripts that use this same header.
  41. ##############################################################################
  42. # Strip the script directory from sys.path() so on case-insensitive
  43. # (WIN32) systems Python doesn't think that the "scons" script is the
  44. # "SCons" package. Replace it with our own library directories
  45. # (version-specific first, in case they installed by hand there,
  46. # followed by generic) so we pick up the right version of the build
  47. # engine modules if they're in either directory.
  48. script_dir = sys.path[0]
  49. if script_dir in sys.path:
  50. sys.path.remove(script_dir)
  51. libs = []
  52. if "SCONS_LIB_DIR" in os.environ:
  53. libs.append(os.environ["SCONS_LIB_DIR"])
  54. local_version = 'scons-local-' + __version__
  55. local = 'scons-local'
  56. if script_dir:
  57. local_version = os.path.join(script_dir, local_version)
  58. local = os.path.join(script_dir, local)
  59. libs.append(os.path.abspath(local_version))
  60. libs.append(os.path.abspath(local))
  61. scons_version = 'scons-%s' % __version__
  62. prefs = []
  63. if sys.platform == 'win32':
  64. # sys.prefix is (likely) C:\Python*;
  65. # check only C:\Python*.
  66. prefs.append(sys.prefix)
  67. prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages'))
  68. else:
  69. # On other (POSIX) platforms, things are more complicated due to
  70. # the variety of path names and library locations. Try to be smart
  71. # about it.
  72. if script_dir == 'bin':
  73. # script_dir is `pwd`/bin;
  74. # check `pwd`/lib/scons*.
  75. prefs.append(os.getcwd())
  76. else:
  77. if script_dir == '.' or script_dir == '':
  78. script_dir = os.getcwd()
  79. head, tail = os.path.split(script_dir)
  80. if tail == "bin":
  81. # script_dir is /foo/bin;
  82. # check /foo/lib/scons*.
  83. prefs.append(head)
  84. head, tail = os.path.split(sys.prefix)
  85. if tail == "usr":
  86. # sys.prefix is /foo/usr;
  87. # check /foo/usr/lib/scons* first,
  88. # then /foo/usr/local/lib/scons*.
  89. prefs.append(sys.prefix)
  90. prefs.append(os.path.join(sys.prefix, "local"))
  91. elif tail == "local":
  92. h, t = os.path.split(head)
  93. if t == "usr":
  94. # sys.prefix is /foo/usr/local;
  95. # check /foo/usr/local/lib/scons* first,
  96. # then /foo/usr/lib/scons*.
  97. prefs.append(sys.prefix)
  98. prefs.append(head)
  99. else:
  100. # sys.prefix is /foo/local;
  101. # check only /foo/local/lib/scons*.
  102. prefs.append(sys.prefix)
  103. else:
  104. # sys.prefix is /foo (ends in neither /usr or /local);
  105. # check only /foo/lib/scons*.
  106. prefs.append(sys.prefix)
  107. temp = [os.path.join(x, 'lib') for x in prefs]
  108. temp.extend([os.path.join(x,
  109. 'lib',
  110. 'python' + sys.version[:3],
  111. 'site-packages') for x in prefs])
  112. prefs = temp
  113. # Add the parent directory of the current python's library to the
  114. # preferences. On SuSE-91/AMD64, for example, this is /usr/lib64,
  115. # not /usr/lib.
  116. try:
  117. libpath = os.__file__
  118. except AttributeError:
  119. pass
  120. else:
  121. # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*.
  122. libpath, tail = os.path.split(libpath)
  123. # Split /usr/libfoo/python* to /usr/libfoo
  124. libpath, tail = os.path.split(libpath)
  125. # Check /usr/libfoo/scons*.
  126. prefs.append(libpath)
  127. try:
  128. import pkg_resources
  129. except ImportError:
  130. pass
  131. else:
  132. # when running from an egg add the egg's directory
  133. try:
  134. d = pkg_resources.get_distribution('scons')
  135. except pkg_resources.DistributionNotFound:
  136. pass
  137. else:
  138. prefs.append(d.location)
  139. # Look first for 'scons-__version__' in all of our preference libs,
  140. # then for 'scons'.
  141. libs.extend([os.path.join(x, scons_version) for x in prefs])
  142. libs.extend([os.path.join(x, 'scons') for x in prefs])
  143. sys.path = libs + sys.path
  144. ##############################################################################
  145. # END STANDARD SCons SCRIPT HEADER
  146. ##############################################################################
  147. import SCons.compat # so pickle will import cPickle instead
  148. import whichdb
  149. import pickle
  150. import imp
  151. import SCons.SConsign
  152. def my_whichdb(filename):
  153. if filename[-7:] == ".dblite":
  154. return "SCons.dblite"
  155. try:
  156. f = open(filename + ".dblite", "rb")
  157. f.close()
  158. return "SCons.dblite"
  159. except IOError:
  160. pass
  161. return _orig_whichdb(filename)
  162. _orig_whichdb = whichdb.whichdb
  163. whichdb.whichdb = my_whichdb
  164. def my_import(mname):
  165. if '.' in mname:
  166. i = mname.rfind('.')
  167. parent = my_import(mname[:i])
  168. fp, pathname, description = imp.find_module(mname[i+1:],
  169. parent.__path__)
  170. else:
  171. fp, pathname, description = imp.find_module(mname)
  172. return imp.load_module(mname, fp, pathname, description)
  173. class Flagger(object):
  174. default_value = 1
  175. def __setitem__(self, item, value):
  176. self.__dict__[item] = value
  177. self.default_value = 0
  178. def __getitem__(self, item):
  179. return self.__dict__.get(item, self.default_value)
  180. Do_Call = None
  181. Print_Directories = []
  182. Print_Entries = []
  183. Print_Flags = Flagger()
  184. Verbose = 0
  185. Readable = 0
  186. def default_mapper(entry, name):
  187. try:
  188. val = eval("entry."+name)
  189. except:
  190. val = None
  191. return str(val)
  192. def map_action(entry, name):
  193. try:
  194. bact = entry.bact
  195. bactsig = entry.bactsig
  196. except AttributeError:
  197. return None
  198. return '%s [%s]' % (bactsig, bact)
  199. def map_timestamp(entry, name):
  200. try:
  201. timestamp = entry.timestamp
  202. except AttributeError:
  203. timestamp = None
  204. if Readable and timestamp:
  205. return "'" + time.ctime(timestamp) + "'"
  206. else:
  207. return str(timestamp)
  208. def map_bkids(entry, name):
  209. try:
  210. bkids = entry.bsources + entry.bdepends + entry.bimplicit
  211. bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs
  212. except AttributeError:
  213. return None
  214. result = []
  215. for i in range(len(bkids)):
  216. result.append(nodeinfo_string(bkids[i], bkidsigs[i], " "))
  217. if result == []:
  218. return None
  219. return "\n ".join(result)
  220. map_field = {
  221. 'action' : map_action,
  222. 'timestamp' : map_timestamp,
  223. 'bkids' : map_bkids,
  224. }
  225. map_name = {
  226. 'implicit' : 'bkids',
  227. }
  228. def field(name, entry, verbose=Verbose):
  229. if not Print_Flags[name]:
  230. return None
  231. fieldname = map_name.get(name, name)
  232. mapper = map_field.get(fieldname, default_mapper)
  233. val = mapper(entry, name)
  234. if verbose:
  235. val = name + ": " + val
  236. return val
  237. def nodeinfo_raw(name, ninfo, prefix=""):
  238. # This just formats the dictionary, which we would normally use str()
  239. # to do, except that we want the keys sorted for deterministic output.
  240. d = ninfo.__dict__
  241. try:
  242. keys = ninfo.field_list + ['_version_id']
  243. except AttributeError:
  244. keys = sorted(d.keys())
  245. l = []
  246. for k in keys:
  247. l.append('%s: %s' % (repr(k), repr(d.get(k))))
  248. if '\n' in name:
  249. name = repr(name)
  250. return name + ': {' + ', '.join(l) + '}'
  251. def nodeinfo_cooked(name, ninfo, prefix=""):
  252. try:
  253. field_list = ninfo.field_list
  254. except AttributeError:
  255. field_list = []
  256. if '\n' in name:
  257. name = repr(name)
  258. outlist = [name+':'] + [_f for _f in [field(x, ninfo, Verbose) for x in field_list] if _f]
  259. if Verbose:
  260. sep = '\n ' + prefix
  261. else:
  262. sep = ' '
  263. return sep.join(outlist)
  264. nodeinfo_string = nodeinfo_cooked
  265. def printfield(name, entry, prefix=""):
  266. outlist = field("implicit", entry, 0)
  267. if outlist:
  268. if Verbose:
  269. print " implicit:"
  270. print " " + outlist
  271. outact = field("action", entry, 0)
  272. if outact:
  273. if Verbose:
  274. print " action: " + outact
  275. else:
  276. print " " + outact
  277. def printentries(entries, location):
  278. if Print_Entries:
  279. for name in Print_Entries:
  280. try:
  281. entry = entries[name]
  282. except KeyError:
  283. sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, location))
  284. else:
  285. try:
  286. ninfo = entry.ninfo
  287. except AttributeError:
  288. print name + ":"
  289. else:
  290. print nodeinfo_string(name, entry.ninfo)
  291. printfield(name, entry.binfo)
  292. else:
  293. for name in sorted(entries.keys()):
  294. entry = entries[name]
  295. try:
  296. ninfo = entry.ninfo
  297. except AttributeError:
  298. print name + ":"
  299. else:
  300. print nodeinfo_string(name, entry.ninfo)
  301. printfield(name, entry.binfo)
  302. class Do_SConsignDB(object):
  303. def __init__(self, dbm_name, dbm):
  304. self.dbm_name = dbm_name
  305. self.dbm = dbm
  306. def __call__(self, fname):
  307. # The *dbm modules stick their own file suffixes on the names
  308. # that are passed in. This is causes us to jump through some
  309. # hoops here to be able to allow the user
  310. try:
  311. # Try opening the specified file name. Example:
  312. # SPECIFIED OPENED BY self.dbm.open()
  313. # --------- -------------------------
  314. # .sconsign => .sconsign.dblite
  315. # .sconsign.dblite => .sconsign.dblite.dblite
  316. db = self.dbm.open(fname, "r")
  317. except (IOError, OSError), e:
  318. print_e = e
  319. try:
  320. # That didn't work, so try opening the base name,
  321. # so that if the actually passed in 'sconsign.dblite'
  322. # (for example), the dbm module will put the suffix back
  323. # on for us and open it anyway.
  324. db = self.dbm.open(os.path.splitext(fname)[0], "r")
  325. except (IOError, OSError):
  326. # That didn't work either. See if the file name
  327. # they specified just exists (independent of the dbm
  328. # suffix-mangling).
  329. try:
  330. open(fname, "r")
  331. except (IOError, OSError), e:
  332. # Nope, that file doesn't even exist, so report that
  333. # fact back.
  334. print_e = e
  335. sys.stderr.write("sconsign: %s\n" % (print_e))
  336. return
  337. except KeyboardInterrupt:
  338. raise
  339. except pickle.UnpicklingError:
  340. sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" % (self.dbm_name, fname))
  341. return
  342. except Exception, e:
  343. sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" % (self.dbm_name, fname, e))
  344. return
  345. if Print_Directories:
  346. for dir in Print_Directories:
  347. try:
  348. val = db[dir]
  349. except KeyError:
  350. sys.stderr.write("sconsign: no dir `%s' in `%s'\n" % (dir, args[0]))
  351. else:
  352. self.printentries(dir, val)
  353. else:
  354. for dir in sorted(db.keys()):
  355. self.printentries(dir, db[dir])
  356. def printentries(self, dir, val):
  357. print '=== ' + dir + ':'
  358. printentries(pickle.loads(val), dir)
  359. def Do_SConsignDir(name):
  360. try:
  361. fp = open(name, 'rb')
  362. except (IOError, OSError), e:
  363. sys.stderr.write("sconsign: %s\n" % (e))
  364. return
  365. try:
  366. sconsign = SCons.SConsign.Dir(fp)
  367. except KeyboardInterrupt:
  368. raise
  369. except pickle.UnpicklingError:
  370. sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % (name))
  371. return
  372. except Exception, e:
  373. sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e))
  374. return
  375. printentries(sconsign.entries, args[0])
  376. ##############################################################################
  377. import getopt
  378. helpstr = """\
  379. Usage: sconsign [OPTIONS] FILE [...]
  380. Options:
  381. -a, --act, --action Print build action information.
  382. -c, --csig Print content signature information.
  383. -d DIR, --dir=DIR Print only info about DIR.
  384. -e ENTRY, --entry=ENTRY Print only info about ENTRY.
  385. -f FORMAT, --format=FORMAT FILE is in the specified FORMAT.
  386. -h, --help Print this message and exit.
  387. -i, --implicit Print implicit dependency information.
  388. -r, --readable Print timestamps in human-readable form.
  389. --raw Print raw Python object representations.
  390. -s, --size Print file sizes.
  391. -t, --timestamp Print timestamp information.
  392. -v, --verbose Verbose, describe each field.
  393. """
  394. opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv",
  395. ['act', 'action',
  396. 'csig', 'dir=', 'entry=',
  397. 'format=', 'help', 'implicit',
  398. 'raw', 'readable',
  399. 'size', 'timestamp', 'verbose'])
  400. for o, a in opts:
  401. if o in ('-a', '--act', '--action'):
  402. Print_Flags['action'] = 1
  403. elif o in ('-c', '--csig'):
  404. Print_Flags['csig'] = 1
  405. elif o in ('-d', '--dir'):
  406. Print_Directories.append(a)
  407. elif o in ('-e', '--entry'):
  408. Print_Entries.append(a)
  409. elif o in ('-f', '--format'):
  410. Module_Map = {'dblite' : 'SCons.dblite',
  411. 'sconsign' : None}
  412. dbm_name = Module_Map.get(a, a)
  413. if dbm_name:
  414. try:
  415. dbm = my_import(dbm_name)
  416. except:
  417. sys.stderr.write("sconsign: illegal file format `%s'\n" % a)
  418. print helpstr
  419. sys.exit(2)
  420. Do_Call = Do_SConsignDB(a, dbm)
  421. else:
  422. Do_Call = Do_SConsignDir
  423. elif o in ('-h', '--help'):
  424. print helpstr
  425. sys.exit(0)
  426. elif o in ('-i', '--implicit'):
  427. Print_Flags['implicit'] = 1
  428. elif o in ('--raw',):
  429. nodeinfo_string = nodeinfo_raw
  430. elif o in ('-r', '--readable'):
  431. Readable = 1
  432. elif o in ('-s', '--size'):
  433. Print_Flags['size'] = 1
  434. elif o in ('-t', '--timestamp'):
  435. Print_Flags['timestamp'] = 1
  436. elif o in ('-v', '--verbose'):
  437. Verbose = 1
  438. if Do_Call:
  439. for a in args:
  440. Do_Call(a)
  441. else:
  442. for a in args:
  443. dbm_name = whichdb.whichdb(a)
  444. if dbm_name:
  445. Map_Module = {'SCons.dblite' : 'dblite'}
  446. dbm = my_import(dbm_name)
  447. Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a)
  448. else:
  449. Do_SConsignDir(a)
  450. sys.exit(0)
  451. # Local Variables:
  452. # tab-width:4
  453. # indent-tabs-mode:nil
  454. # End:
  455. # vim: set expandtab tabstop=4 shiftwidth=4: