Mercurial > hg
comparison setup.py @ 33114:8b20338b989e
setup: prefer using the system hg to interact with the local repository
Add a findhg() function that tries to be smarter about figuring out how to run
hg for examining the local repository. It first tries running "hg" from the
user's PATH, with the default HGRCPATH settings intact, but with HGPLAIN
enabled. This will generally use the same version of mercurial and the same
settings used to originally clone the repository, and should have a higher
chance of working successfully than trying to run the hg script from the local
repository. If that fails findhg() falls back to the existing behavior of
running the local hg script.
author | Adam Simpkins <simpkins@fb.com> |
---|---|
date | Tue, 27 Jun 2017 16:15:32 -0700 |
parents | fc290a39590d |
children | 6ef5f0c95d64 |
comparison
equal
deleted
inserted
replaced
33113:fc290a39590d | 33114:8b20338b989e |
---|---|
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') |