146 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, |
146 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, |
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 def runhg(cmd, env): |
151 class hgcommand(object): |
152 returncode, out, err = runcmd(cmd, env) |
152 def __init__(self): |
153 # If root is executing setup.py, but the repository is owned by |
153 self.cmd = [sys.executable, 'hg'] |
154 # another user (as in "sudo python setup.py install") we will get |
154 self.env = gethgenv() |
155 # trust warnings since the .hg/hgrc file is untrusted. That is |
155 |
156 # fine, we don't want to load it anyway. Python may warn about |
156 def run(self, args): |
157 # a missing __init__.py in mercurial/locale, we also ignore that. |
157 cmd = self.cmd + args |
158 err = [e for e in err.splitlines() |
158 returncode, out, err = runcmd(cmd, self.env) |
159 if not e.startswith(b'not trusting file') \ |
159 # If root is executing setup.py, but the repository is owned by |
160 and not e.startswith(b'warning: Not importing') \ |
160 # another user (as in "sudo python setup.py install") we will get |
161 and not e.startswith(b'obsolete feature not enabled')] |
161 # trust warnings since the .hg/hgrc file is untrusted. That is |
162 if err or returncode != 0: |
162 # fine, we don't want to load it anyway. Python may warn about |
163 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) |
163 # a missing __init__.py in mercurial/locale, we also ignore that. |
164 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr) |
164 err = [e for e in err.splitlines() |
165 return '' |
165 if not e.startswith(b'not trusting file') \ |
166 return out |
166 and not e.startswith(b'warning: Not importing') \ |
167 |
167 and not e.startswith(b'obsolete feature not enabled')] |
|
168 if err or returncode != 0: |
|
169 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) |
|
170 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr) |
|
171 return '' |
|
172 return out |
168 |
173 |
169 def gethgenv(): |
174 def gethgenv(): |
170 # Execute hg out of this directory with a custom environment which takes |
175 # Execute hg out of this directory with a custom environment which takes |
171 # care to not use any hgrc files and do no localization. |
176 # care to not use any hgrc files and do no localization. |
172 env = {'HGMODULEPOLICY': 'py', |
177 env = {'HGMODULEPOLICY': 'py', |
178 if 'SystemRoot' in os.environ: |
183 if 'SystemRoot' in os.environ: |
179 # SystemRoot is required by Windows to load various DLLs. See: |
184 # SystemRoot is required by Windows to load various DLLs. See: |
180 # https://bugs.python.org/issue13524#msg148850 |
185 # https://bugs.python.org/issue13524#msg148850 |
181 env['SystemRoot'] = os.environ['SystemRoot'] |
186 env['SystemRoot'] = os.environ['SystemRoot'] |
182 |
187 |
183 env = gethgenv() |
|
184 version = '' |
188 version = '' |
185 |
189 |
186 if os.path.isdir('.hg'): |
190 if os.path.isdir('.hg'): |
187 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n'] |
191 hg = hgcommand() |
188 numerictags = [t for t in runhg(cmd, env).split() if t[0:1].isdigit()] |
192 cmd = ['log', '-r', '.', '--template', '{tags}\n'] |
189 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip() |
193 numerictags = [t for t in hg.run(cmd).split() if t[0:1].isdigit()] |
|
194 hgid = hg.run(['id', '-i']).strip() |
190 if not hgid: |
195 if not hgid: |
191 # Bail out if hg is having problems interacting with this repository, |
196 # Bail out if hg is having problems interacting with this repository, |
192 # rather than falling through and producing a bogus version number. |
197 # rather than falling through and producing a bogus version number. |
193 # Continuing with an invalid version number will break extensions |
198 # Continuing with an invalid version number will break extensions |
194 # that define minimumhgversion. |
199 # that define minimumhgversion. |
196 if numerictags: # tag(s) found |
201 if numerictags: # tag(s) found |
197 version = numerictags[-1] |
202 version = numerictags[-1] |
198 if hgid.endswith('+'): # propagate the dirty status to the tag |
203 if hgid.endswith('+'): # propagate the dirty status to the tag |
199 version += '+' |
204 version += '+' |
200 else: # no tag found |
205 else: # no tag found |
201 ltagcmd = [sys.executable, 'hg', 'parents', '--template', |
206 ltagcmd = ['parents', '--template', '{latesttag}'] |
202 '{latesttag}'] |
207 ltag = hg.run(ltagcmd) |
203 ltag = runhg(ltagcmd, env) |
208 changessincecmd = ['log', '-T', 'x\n', '-r', "only(.,'%s')" % ltag] |
204 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r', |
209 changessince = len(hg.run(changessincecmd).splitlines()) |
205 "only(.,'%s')" % ltag] |
|
206 changessince = len(runhg(changessincecmd, env).splitlines()) |
|
207 version = '%s+%s-%s' % (ltag, changessince, hgid) |
210 version = '%s+%s-%s' % (ltag, changessince, hgid) |
208 if version.endswith('+'): |
211 if version.endswith('+'): |
209 version += time.strftime('%Y%m%d') |
212 version += time.strftime('%Y%m%d') |
210 elif os.path.exists('.hg_archival.txt'): |
213 elif os.path.exists('.hg_archival.txt'): |
211 kw = dict([[t.strip() for t in l.split(':', 1)] |
214 kw = dict([[t.strip() for t in l.split(':', 1)] |
405 f.write('# empty\n') |
408 f.write('# empty\n') |
406 |
409 |
407 # here no extension enabled, disabled() lists up everything |
410 # here no extension enabled, disabled() lists up everything |
408 code = ('import pprint; from mercurial import extensions; ' |
411 code = ('import pprint; from mercurial import extensions; ' |
409 'pprint.pprint(extensions.disabled())') |
412 'pprint.pprint(extensions.disabled())') |
410 returncode, out, err = runcmd([sys.executable, '-c', code], env) |
413 returncode, out, err = runcmd([sys.executable, '-c', code], gethgenv()) |
411 if err or returncode != 0: |
414 if err or returncode != 0: |
412 raise DistutilsExecError(err) |
415 raise DistutilsExecError(err) |
413 |
416 |
414 with open(self._indexfilename, 'w') as f: |
417 with open(self._indexfilename, 'w') as f: |
415 f.write('# this file is autogenerated by setup.py\n') |
418 f.write('# this file is autogenerated by setup.py\n') |