147 stderr=subprocess.PIPE, env=env) |
147 stderr=subprocess.PIPE, env=env) |
148 out, err = p.communicate() |
148 out, err = p.communicate() |
149 return p.returncode, out, err |
149 return p.returncode, out, err |
150 |
150 |
151 class hgcommand(object): |
151 class hgcommand(object): |
152 def __init__(self): |
152 def __init__(self, cmd, env): |
153 self.cmd = [sys.executable, 'hg'] |
153 self.cmd = cmd |
154 self.env = gethgenv() |
154 self.env = env |
155 |
155 |
156 def run(self, args): |
156 def run(self, args): |
157 cmd = self.cmd + args |
157 cmd = self.cmd + args |
158 returncode, out, err = runcmd(cmd, self.env) |
158 returncode, out, err = runcmd(cmd, self.env) |
159 # If root is executing setup.py, but the repository is owned by |
159 # If root is executing setup.py, but the repository is owned by |
169 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) |
169 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) |
170 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr) |
170 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr) |
171 return '' |
171 return '' |
172 return out |
172 return out |
173 |
173 |
174 def gethgenv(): |
174 def findhg(): |
|
175 """Try to figure out how we should invoke hg for examining the local |
|
176 repository contents. |
|
177 |
|
178 Returns an hgcommand object.""" |
|
179 # By default, prefer the "hg" command in the user's path. This was |
|
180 # presumably the hg command that the user used to create this repository. |
|
181 # |
|
182 # This repository may require extensions or other settings that would not |
|
183 # be enabled by running the hg script directly from this local repository. |
|
184 hgenv = os.environ.copy() |
|
185 # Use HGPLAIN to disable hgrc settings that would change output formatting, |
|
186 # and disable localization for the same reasons. |
|
187 hgenv['HGPLAIN'] = '1' |
|
188 hgenv['LANGUAGE'] = 'C' |
|
189 hgcmd = ['hg'] |
|
190 # Run a simple "hg log" command just to see if using hg from the user's |
|
191 # path works and can successfully interact with this repository. |
|
192 check_cmd = ['log', '-r.', '-Ttest'] |
|
193 try: |
|
194 retcode, out, err = runcmd(hgcmd + check_cmd, hgenv) |
|
195 except EnvironmentError: |
|
196 retcode = -1 |
|
197 if retcode == 0: |
|
198 return hgcommand(hgcmd, hgenv) |
|
199 |
|
200 # Fall back to trying the local hg installation. |
|
201 hgenv = localhgenv() |
|
202 # Don't source any system hgrc files when using the local hg. |
|
203 hgenv['HGRCPATH'] = '' |
|
204 hgcmd = [sys.executable, 'hg'] |
|
205 try: |
|
206 retcode, out, err = runcmd(hgcmd + check_cmd, hgenv) |
|
207 except EnvironmentError: |
|
208 retcode = -1 |
|
209 if retcode == 0: |
|
210 return hgcommand(hgcmd, hgenv) |
|
211 |
|
212 raise SystemExit('Unable to find a working hg binary to extract the ' |
|
213 'version from the repository tags') |
|
214 |
|
215 def localhgenv(): |
|
216 """Get an environment dictionary to use for invoking or importing |
|
217 mercurial from the local repository.""" |
175 # Execute hg out of this directory with a custom environment which takes |
218 # Execute hg out of this directory with a custom environment which takes |
176 # care to not use any hgrc files and do no localization. |
219 # care to not use any hgrc files and do no localization. |
177 env = {'HGMODULEPOLICY': 'py', |
220 env = {'HGMODULEPOLICY': 'py', |
178 'HGRCPATH': '', |
221 'HGRCPATH': '', |
179 'LANGUAGE': 'C', |
222 'LANGUAGE': 'C', |
186 env['SystemRoot'] = os.environ['SystemRoot'] |
229 env['SystemRoot'] = os.environ['SystemRoot'] |
187 |
230 |
188 version = '' |
231 version = '' |
189 |
232 |
190 if os.path.isdir('.hg'): |
233 if os.path.isdir('.hg'): |
191 hg = hgcommand() |
234 hg = findhg() |
192 cmd = ['log', '-r', '.', '--template', '{tags}\n'] |
235 cmd = ['log', '-r', '.', '--template', '{tags}\n'] |
193 numerictags = [t for t in hg.run(cmd).split() if t[0:1].isdigit()] |
236 numerictags = [t for t in hg.run(cmd).split() if t[0:1].isdigit()] |
194 hgid = hg.run(['id', '-i']).strip() |
237 hgid = hg.run(['id', '-i']).strip() |
195 if not hgid: |
238 if not hgid: |
196 # Bail out if hg is having problems interacting with this repository, |
239 # Bail out if hg is having problems interacting with this repository, |
408 f.write('# empty\n') |
451 f.write('# empty\n') |
409 |
452 |
410 # here no extension enabled, disabled() lists up everything |
453 # here no extension enabled, disabled() lists up everything |
411 code = ('import pprint; from mercurial import extensions; ' |
454 code = ('import pprint; from mercurial import extensions; ' |
412 'pprint.pprint(extensions.disabled())') |
455 'pprint.pprint(extensions.disabled())') |
413 returncode, out, err = runcmd([sys.executable, '-c', code], gethgenv()) |
456 returncode, out, err = runcmd([sys.executable, '-c', code], |
|
457 localhgenv()) |
414 if err or returncode != 0: |
458 if err or returncode != 0: |
415 raise DistutilsExecError(err) |
459 raise DistutilsExecError(err) |
416 |
460 |
417 with open(self._indexfilename, 'w') as f: |
461 with open(self._indexfilename, 'w') as f: |
418 f.write('# this file is autogenerated by setup.py\n') |
462 f.write('# this file is autogenerated by setup.py\n') |