Patchwork [6,of,7] extdata: use subprocess so we don't have to chdir() manually

login
register
mail settings
Submitter Yuya Nishihara
Date Oct. 1, 2017, noon
Message ID <b3a36705720f5ed1e7cc.1506859217@mimosa>
Download mbox | patch
Permalink /patch/24336/
State Accepted
Headers show

Comments

Yuya Nishihara - Oct. 1, 2017, noon
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1506856376 -3600
#      Sun Oct 01 12:12:56 2017 +0100
# Node ID b3a36705720f5ed1e7cc5129b27450ca59c7952b
# Parent  88bc2465f1c9dd7c9a7f76eec68530b1a62f3794
extdata: use subprocess so we don't have to chdir() manually

Patch

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -13,6 +13,7 @@  import hashlib
 import os
 import re
 import socket
+import subprocess
 import weakref
 
 from .i18n import _
@@ -1038,20 +1039,18 @@  def extdatasource(repo, source):
         raise error.Abort(_("unknown extdata source '%s'") % source)
 
     data = {}
-    if spec.startswith("shell:"):
-        # external commands should be run relative to the repo root
-        cmd = spec[6:]
-        cwd = os.getcwd()
-        os.chdir(repo.root)
-        try:
-            src = util.popen(cmd)
-        finally:
-            os.chdir(cwd)
-    else:
-        # treat as a URL or file
-        src = url.open(repo.ui, spec)
-
+    src = proc = None
     try:
+        if spec.startswith("shell:"):
+            # external commands should be run relative to the repo root
+            cmd = spec[6:]
+            proc = subprocess.Popen(cmd, shell=True, bufsize=-1,
+                                    close_fds=util.closefds,
+                                    stdout=subprocess.PIPE, cwd=repo.root)
+            src = proc.stdout
+        else:
+            # treat as a URL or file
+            src = url.open(repo.ui, spec)
         for l in src:
             if " " in l:
                 k, v = l.strip().split(" ", 1)
@@ -1064,7 +1063,10 @@  def extdatasource(repo, source):
             except (error.LookupError, error.RepoLookupError):
                 pass # we ignore data for nodes that don't exist locally
     finally:
-        src.close()
+        if proc:
+            proc.communicate()
+        if src:
+            src.close()
 
     return data