comparison src/tools/utils.py @ 1858:06e13ae616cf

tools (utils): improved repository version detection: - getRepositoryData has 2 new option: is_path to give absolute path instead of module name, and save_dir_path to save the repository data in a pickled dictionnary - if "hg" executable doesn't work, a .hg_data dictionnary is checked if present in module root path
author Goffi <goffi@goffi.org>
date Sun, 28 Feb 2016 13:42:31 +0100
parents 2d2617930f97
children 2daf7b4c6756
comparison
equal deleted inserted replaced
1857:2d2617930f97 1858:06e13ae616cf
51 template_time = u"%H:%M:%SZ" 51 template_time = u"%H:%M:%SZ"
52 template = u"{}T{}".format(template_date, template_time) if with_time else template_date 52 template = u"{}T{}".format(template_date, template_time) if with_time else template_date
53 return datetime.datetime.utcfromtimestamp(time.time() if timestamp is None else timestamp).strftime(template) 53 return datetime.datetime.utcfromtimestamp(time.time() if timestamp is None else timestamp).strftime(template)
54 54
55 55
56 def getRepositoryData(module, as_string=True): 56 def getRepositoryData(module, as_string=True, is_path=False, save_dir_path=None):
57 """Retrieve info on current mecurial repository 57 """Retrieve info on current mecurial repository
58 58
59 @param module: module to look for (e.g. sat, libervia) 59 Data is gotten by using the following methods, in order:
60 - using "hg" executable
61 - looking for a ".hg_data" file in the root of the module
62 this file must contain the data dictionnary serialized with pickle
63 - looking for a .hg/dirstate in parent directory of module (or in module/.hg if
64 is_path is True), and parse dirstate file to get revision
65 @param module(unicode): module to look for (e.g. sat, libervia)
66 module can be a path if is_path is True (see below)
60 @param as_string(bool): if True return a string, else return a dictionary 67 @param as_string(bool): if True return a string, else return a dictionary
68 @param is_path(bool): if True "module" is not handled as a module name, but as an
69 absolute path to the parent of a ".hg" directory
70 @param save_path(str, None): if not None, the value will be saved to given path as a pickled dict
71 /!\\ the .hg_data file in the given directory will be overwritten
61 @return (unicode, dictionary): retrieved info in a nice string, 72 @return (unicode, dictionary): retrieved info in a nice string,
62 or a dictionary with retrieved data (key is not present if data is not found), 73 or a dictionary with retrieved data (key is not present if data is not found),
63 key can be: 74 key can be:
64 - node: full revision number (40 bits) 75 - node: full revision number (40 bits)
65 - branch: branch name 76 - branch: branch name
67 - tag: latest tag used in hierarchie 78 - tag: latest tag used in hierarchie
68 """ 79 """
69 from distutils.spawn import find_executable 80 from distutils.spawn import find_executable
70 import subprocess 81 import subprocess
71 KEYS=("node", "node_short", "branch", "date", "tag") 82 KEYS=("node", "node_short", "branch", "date", "tag")
72 repos_root = os.path.dirname(module.__file__) 83 ori_cwd = os.getcwd()
84
85 if is_path:
86 repos_root = module
87 else:
88 repos_root = os.path.dirname(module.__file__)
89
73 hg_path = find_executable('hg') 90 hg_path = find_executable('hg')
74 91
75 if hg_path is not None: 92 if hg_path is not None:
76 os.chdir(repos_root) 93 os.chdir(repos_root)
77 try: 94 try:
86 pass 103 pass
87 else: 104 else:
88 hg_data = {} 105 hg_data = {}
89 106
90 if not hg_data: 107 if not hg_data:
91 log.debug(u"Mercurial not available or working, trying to get data from dirstate") 108 # .hg_data pickle method
92 os.chdir(os.path.relpath('..', repos_root)) 109 log.debug(u"Mercurial not available or working, trying other methods")
110 if save_dir_path is None:
111 log.debug(u"trying .hg_data method")
112
113 try:
114 with open(os.path.join(repos_root, '.hg_data')) as f:
115 import cPickle as pickle
116 hg_data = pickle.load(f)
117 except IOError as e:
118 log.debug(u"Can't access .hg_data file: {}".format(e))
119 except pickle.UnpicklingError:
120 log.warning(u"Error while reading {}, can't get repos data".format(f.name))
121
122 if not hg_data:
123 # .hg/dirstate method
124 log.debug(u"trying dirstate method")
125 if is_path:
126 os.chdir(repos_root)
127 else:
128 os.chdir(os.path.relpath('..', repos_root))
93 try: 129 try:
94 with open('.hg/dirstate') as hg_dirstate: 130 with open('.hg/dirstate') as hg_dirstate:
95 hg_data['node'] = hg_dirstate.read(20).encode('hex') 131 hg_data['node'] = hg_dirstate.read(20).encode('hex')
96 hg_data['node_short'] = hg_data['node'][:12] 132 hg_data['node_short'] = hg_data['node'][:12]
97 except IOError: 133 except IOError:
98 log.warning(u"Can't access repository data") 134 log.warning(u"Can't access repository data")
135
136 # we restore original working dir
137 os.chdir(ori_cwd)
138
139 # data saving
140 if save_dir_path is not None and hg_data:
141 if not os.path.isdir(save_dir_path):
142 log.warning(u"Given path is not a directory, can't save data")
143 else:
144 import cPickle as pickle
145 dest_path = os.path.join(save_dir_path, ".hg_data")
146 try:
147 with open(dest_path, 'w') as f:
148 pickle.dump(hg_data, f, 2)
149 except IOError as e:
150 log.warning(u"Can't save file to {path}: {reason}".format(
151 path=dest_path, reason=e))
152 else:
153 log.debug(u"repository data saved to {}".format(dest_path))
99 154
100 if as_string: 155 if as_string:
101 if not hg_data: 156 if not hg_data:
102 return u'repository data unknown' 157 return u'repository data unknown'
103 strings = [u'rev', hg_data['node_short']] 158 strings = [u'rev', hg_data['node_short']]