From patchwork Thu Jan 6 21:40:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Holdsworth X-Patchwork-Id: 12705749 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CE199C433F5 for ; Thu, 6 Jan 2022 21:41:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244329AbiAFVlE (ORCPT ); Thu, 6 Jan 2022 16:41:04 -0500 Received: from mail-dm6nam12on2043.outbound.protection.outlook.com ([40.107.243.43]:57313 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S244184AbiAFVlB (ORCPT ); Thu, 6 Jan 2022 16:41:01 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iUvDVz7Or8XNA+wa4GcluGOyD/vX/IHiRIDAptdUFa5Zfc+9LKpwJSZwkY2sXOlcSOVVaKqFksLkG4pUlDpiWw315B38GztMIzCj26Fufgyza4AYARdydDs05aVQLwZK9wAKTU8BPNpVN2fMQne9VtFqm/Jd169utSwqy5nfk1aJVeI/VXjdWDV5AS5ylBBOgrkMDOS61e5052cC8iN5dbHsWG7s85gT9ndyIcusAW4XW+jjD3mvRQQ46lfqN7CbbZJylcJW7wbAa0vDO0RtR0kSMtVY4AbS658uOaB18qN+rnFi+fB2sFl5rbkOeKBXR5KFU8bM+gl1twP7H6C+2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=q4X0DIDtFaYJ9pd3LUEpT2iu/aZPnfb3F7zKXUJzzZ4=; b=Q5SsOjQCoLwYNvq3EbUypJiBs02JeUxh0e9cFNDYDj469cKsRiJ7m2mt546xYEXXE9ILo1GiqbxbshVB0PY7TSgFlgbIusisTqy6/CJVw5Y5ZVhR2sfhTM+Do+DqLSNwMCR3F5hJSuQaOMEEa4H6pwfgJVFkd/xQw19Ea/TirJaFdQYk5FHS2D4aJXPSIXPcEADaT09yqzTrP0DKjJdRcbIBL8G4F8wbscmUiH4I+PFruvticjJBKBHFAnRE3Mg94wmBUBaf9tzPQTbVPHCW3p4xRtegKZ+S+ooDmcNUfmiEdAXfGMHR7PQU5AkP+oMTMuA+JkoiJvmLt8IWJ0+2eQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=q4X0DIDtFaYJ9pd3LUEpT2iu/aZPnfb3F7zKXUJzzZ4=; b=XSfs6vHYuCFs+zrYLYqfgbXtOpU+LTfXvqWCXOb7rwsGBWLi076SFFYqWCFHah9Aoa8plpBTDCXksyqr659Um8guuGs1kNY9N07nD1GikKI1s0G5BBtsp3BRDp99abWIxmc79ty8qfG/Xi93bWGGxvtCW7/Nlxd3Tbmlcpl68ikYgvvBYLup4ZW/bn6Nugj5s0Ah3f1Rq3OeEInL3Al7EbZGVV6O3LeMaHgA8NzHwjoTG0qn75vIJGBkL0uw74teYDDMRmxoCSgaX2xhgLU+xpPBUB+NPn2aIPsFd8vLX8nuyD89cfHTJtIm9NGujupRllVgDS7LvqJRx3nRQAmZ3g== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from BL0PR12MB4849.namprd12.prod.outlook.com (2603:10b6:208:1c2::17) by MN2PR12MB3854.namprd12.prod.outlook.com (2603:10b6:208:16a::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4867.10; Thu, 6 Jan 2022 21:41:00 +0000 Received: from BL0PR12MB4849.namprd12.prod.outlook.com ([fe80::509e:bbb9:e1fb:26ed]) by BL0PR12MB4849.namprd12.prod.outlook.com ([fe80::509e:bbb9:e1fb:26ed%4]) with mapi id 15.20.4867.009; Thu, 6 Jan 2022 21:41:00 +0000 From: Joel Holdsworth To: git@vger.kernel.org, Luke Diamand , Junio C Hamano , Eric Sunshine Cc: Tzadik Vanderhoof , Dorgon Chang , Joachim Kuebart , Daniel Levin , Johannes Schindelin , Ben Keene , Andrew Oakley , Joel Holdsworth Subject: [PATCH v2 1/3] git-p4: don't select shell mode using the type of the command argument Date: Thu, 6 Jan 2022 21:40:33 +0000 Message-Id: <20220106214035.90725-2-jholdsworth@nvidia.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220106214035.90725-1-jholdsworth@nvidia.com> References: <20220106214035.90725-1-jholdsworth@nvidia.com> X-ClientProxiedBy: AM8P190CA0030.EURP190.PROD.OUTLOOK.COM (2603:10a6:20b:219::35) To BL0PR12MB4849.namprd12.prod.outlook.com (2603:10b6:208:1c2::17) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 23f32419-4ba1-4d9a-b554-08d9d15d3ad3 X-MS-TrafficTypeDiagnostic: MN2PR12MB3854:EE_ X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:2582; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: vxGWyCa+ORpI5uKhULX7fXlOdjKN8BuXQS+9uProBgf8pWVqxQa7NrCxl8JHoOu6LsuM8oISzz96bihX0hlEAdt6mU4XZ8mhsjRCI/WVQkGgA1wGIPxgNUe2SCwWrsGPFHjbZNs6qhre4BbBt5KM7pgMT7vaOSs+F1+aMTR++NNgjuikmjT3TS15ILYf2MPst9PX/o4cWC/akXc/AV+LYiB0FqjA3/3NKX2D8rMuSHOOIGrnQt31KMi1gNmB0ZIErMYF1biwywN1y2CshKfrv1OHxhssFWDygYxxq1bngnwyH1uV+6bdyH8bizZIrd3dvkh3vyA0APONNTB77kmLbCPGd2EEo6hutnMkH/yjbQhp3C5pAjunKWgaRLUgA4XH17HqZMTL9w1a4qwMOLO3mEog2N0EZ45AyQ2SUsLZIJBsvI2BRiop2ZjNWKX0jg8iXHSqWzpOullHLcyVE5rASGdgpp2wlnaFOQuRt+0jYdGsSAzP9hSje1O9/qLiI5OWvHQRkn9H+IRsro6GTpH2uxzwymtPB62OrjUTTPp72NkOk+mM3D1jYBG4+kSBLEnwb466PKhlLFaxF/Yi5k8KAZj1CJTD5gX7+pdcfS9POMc6xw8tqQjjsKu+1NnKQS7Q9KHdzVstlD954JKeuDzNfw/SRY4yZOH55bZOL5P+vSMh8XyrAZe9EkZ0TsZ7IhI29llU15KEPWIONMp0bMAwH+GDwrqGU72SxmiEu6a1htM= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BL0PR12MB4849.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(38100700002)(508600001)(26005)(66556008)(66476007)(83380400001)(186003)(4326008)(38350700002)(8936002)(66946007)(8676002)(36756003)(2616005)(7416002)(54906003)(6512007)(6666004)(107886003)(52116002)(2906002)(30864003)(6486002)(316002)(5660300002)(6506007)(110136005)(1076003)(55236004)(86362001)(403724002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: JGYiL5aJg02NJIh6t665hGI2t+pgvfwlJTepUUgdKHxZHwQu9MvlMcF+uYo0t5LgVnG5gSm8gDdMLfSXAaFs8/FKiGpxwfSqie4l05tTzVukmJaLFuX+CGHwEir5VbiSn1GHXfCVXavpUXFWh7sg23ZNMO0LfSuupx6f+4+lTTuEL1/pNFbyvzvZKvX7qF8umZAvqf1HbyFvz45ZpJvP/BKv7/dPP1PQb1sH0reZxGztgtsGRg24+IpgrVYZ5bpqROK/wnLLOgN4Qff7acN5mTvdz/2BDMpvB0WGFFX8q/xoDb2MeipNQOk4+6UEnSRnnmWMkY85n3eCM66oZsMOF73CJjBBofOBVSFGGgZQPrBuLPk/NbxjAdk07ApAhI3mPsJb9FBcEOsXj/AlOgvGHNfPBRoXFTJiSy/iqFs81szhhhRU1WYjmzNSQcXXqAcfWqga7+Z+gKNfdSc4oU9xkZQ22Ad6V5c2bEGbQzizBH55jrgnZ1GrapNWbzC68tbt5xOoJG8fXsWw19PTjHkBpFN0jMoYuLsYaaAsTjsdc6R+8aQC9jiZlax+20tJReW5oiEF9W9o7067HLklM91nnc9Ly/cg8iqBMlo24gBhEroGjwHZG6/OM1Bkc8oR7UsjvsqHKjZi3zgZGPYet8JaLYTuBqKMotafpaiMv251o12fBRN8Y+gxq8fExR6+6B9w0G75tKsTekJcdCmAYkND1nZ5git2CbETphfsjkipLUfSnmUtvjWO/S0E/Dlqs+rP//+d2kzHgSi0/5m8zFEb7d3eEJovhhWRg3NH06wgZkVeYaoyXDPqXHyi+oDcwfBcVdvcnrQo9PafVzAJSFerhPFKBK2OSd2J/aoSaOO+OpYLR5qk4b06/IrML9Bg8c5XG1iPN9m6KsQPwJfMRKfpkxSYL5BSFJJQxFuOdRPUc1akYsuJxjz1WnXVmEg1kJpcMBQvvK+oH032d5ff5HThm5gOS5hrGKFhzLYnIvNbN1a0NZrROzW/WBbfb/2sRsabs7V9HQl4ec3rSfqyuYUHK6Kcn6fhRNJ65oN/AaKAso1AixwobMLJjrQgcgw2pZr0lHkFFOdpKnO6yddWSsqnb+vkfvCLVRG2r5nBRK6LDPZQYKdfao+SQsMPckOx3ngFRUNVP8HBsuol9SeOPJzx27VQQWdNs8FGOtVg2TfbliD3bl31UjcJhaK2cp3hD3RN1RDeIKjLEkzoFFpk7XWcpdoTjQLMwUPEEgHjeUo9HU/HcoAa939HSBXodVvYJty3n6FIk8gbM5bkW/R/U978UmE/pEAexmrQHG0S3zzOmZYV1RbOgsB808jkRppbmHawX+Z/owjEBkqLDuWVH9avgD2cd6cb61KxhkI4R70sXEbPFUuU6K6dcZQzXQhqDDcQluo6rGZaN2nF5r82xCvGP2vfecQockeuN0nKLrroZZcjF3fRnu/Jq2NvgfYDSCosDzhS6I/RsTarIGiY6oSeD1nvDmeNLDdCB1oG8RLBhGLcKuuL+gJlpK6Rn/BoidJ1vjxJE8mAn8BBvzOY0L0zvmXBxICgyp24iVQZ3BIE/21crFf/kzC1SS69iezYRDxtRlZOvL9Q3ECvNmqlAmP48J1Q7hVFMUOwlIZ5TRE9lZs= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 23f32419-4ba1-4d9a-b554-08d9d15d3ad3 X-MS-Exchange-CrossTenant-AuthSource: BL0PR12MB4849.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Jan 2022 21:41:00.1096 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: PJhVXWKoIntRynyFCnL45WmtSlYn3Mqg13g1XTshyoa1ClOkqFghnCcI7m9rvnqHTRvdXqGaCURW0AGZpvMflA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB3854 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Previously, the script would invoke subprocess functions setting the shell argument True if the command argument was a string, setting it False otherwise. This patch replaces this implicit type-driven behaviour with explicit shell arguments specified by the caller. The apparent motive for the implict behaviour is that the subprocess functions do not divide command strings into args. Invoking subprocess.call("echo hello") will attempt to execute a program by the name "echo hello". With subprocess.call("echo hello", shell=True), sh -c "echo hello" will be executed instead, which will cause the command and args to be divided by spaces. Eventually, all usage of shell=True, that is not necessary for some purpose beyond parsing command strings, should be removed. For now, this patch makes the usage of shells explicit. Signed-off-by: Joel Holdsworth --- This version adds a missing signoff. git-p4.py | 126 +++++++++++++++++++++++++++--------------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/git-p4.py b/git-p4.py index 986595bef0..7ec90388b6 100755 --- a/git-p4.py +++ b/git-p4.py @@ -276,12 +276,11 @@ def run_hook_command(cmd, param): return subprocess.call(cli, shell=use_shell) -def write_pipe(c, stdin): +def write_pipe(c, stdin, *k, **kw): if verbose: sys.stderr.write('Writing pipe: %s\n' % str(c)) - expand = not isinstance(c, list) - p = subprocess.Popen(c, stdin=subprocess.PIPE, shell=expand) + p = subprocess.Popen(c, stdin=subprocess.PIPE, *k, **kw) pipe = p.stdin val = pipe.write(stdin) pipe.close() @@ -290,13 +289,13 @@ def write_pipe(c, stdin): return val -def p4_write_pipe(c, stdin): +def p4_write_pipe(c, stdin, *k, **kw): real_cmd = p4_build_cmd(c) if bytes is not str and isinstance(stdin, str): stdin = encode_text_stream(stdin) - return write_pipe(real_cmd, stdin) + return write_pipe(real_cmd, stdin, *k, **kw) -def read_pipe_full(c): +def read_pipe_full(c, *k, **kw): """ Read output from command. Returns a tuple of the return status, stdout text and stderr text. @@ -304,19 +303,19 @@ def read_pipe_full(c): if verbose: sys.stderr.write('Reading pipe: %s\n' % str(c)) - expand = not isinstance(c, list) - p = subprocess.Popen(c, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=expand) + p = subprocess.Popen( + c, stdout=subprocess.PIPE, stderr=subprocess.PIPE, *k, **kw) (out, err) = p.communicate() return (p.returncode, out, decode_text_stream(err)) -def read_pipe(c, ignore_error=False, raw=False): +def read_pipe(c, ignore_error=False, raw=False, *k, **kw): """ Read output from command. Returns the output text on success. On failure, terminates execution, unless ignore_error is True, when it returns an empty string. If raw is True, do not attempt to decode output text. """ - (retcode, out, err) = read_pipe_full(c) + (retcode, out, err) = read_pipe_full(c, *k, **kw) if retcode != 0: if ignore_error: out = "" @@ -326,26 +325,25 @@ def read_pipe(c, ignore_error=False, raw=False): out = decode_text_stream(out) return out -def read_pipe_text(c): +def read_pipe_text(c, *k, **kw): """ Read output from a command with trailing whitespace stripped. On error, returns None. """ - (retcode, out, err) = read_pipe_full(c) + (retcode, out, err) = read_pipe_full(c, *k, **kw) if retcode != 0: return None else: return decode_text_stream(out).rstrip() -def p4_read_pipe(c, ignore_error=False, raw=False): +def p4_read_pipe(c, ignore_error=False, raw=False, *k, **kw): real_cmd = p4_build_cmd(c) - return read_pipe(real_cmd, ignore_error, raw=raw) + return read_pipe(real_cmd, ignore_error, raw=raw, *k, **kw) -def read_pipe_lines(c, raw=False): +def read_pipe_lines(c, raw=False, *k, **kw): if verbose: sys.stderr.write('Reading pipe: %s\n' % str(c)) - expand = not isinstance(c, list) - p = subprocess.Popen(c, stdout=subprocess.PIPE, shell=expand) + p = subprocess.Popen(c, stdout=subprocess.PIPE, *k, **kw) pipe = p.stdout lines = pipe.readlines() if not raw: @@ -354,10 +352,10 @@ def read_pipe_lines(c, raw=False): die('Command failed: %s' % str(c)) return lines -def p4_read_pipe_lines(c): +def p4_read_pipe_lines(c, *k, **kw): """Specifically invoke p4 on the command supplied. """ real_cmd = p4_build_cmd(c) - return read_pipe_lines(real_cmd) + return read_pipe_lines(real_cmd, *k, **kw) def p4_has_command(cmd): """Ask p4 for help on this command. If it returns an error, the @@ -388,21 +386,19 @@ def p4_has_move_command(): # assume it failed because @... was invalid changelist return True -def system(cmd, ignore_error=False): - expand = not isinstance(cmd, list) +def system(cmd, ignore_error=False, *k, **kw): if verbose: sys.stderr.write("executing %s\n" % str(cmd)) - retcode = subprocess.call(cmd, shell=expand) + retcode = subprocess.call(cmd, *k, **kw) if retcode and not ignore_error: raise CalledProcessError(retcode, cmd) return retcode -def p4_system(cmd): +def p4_system(cmd, *k, **kw): """Specifically invoke p4 as the system command. """ real_cmd = p4_build_cmd(cmd) - expand = not isinstance(real_cmd, list) - retcode = subprocess.call(real_cmd, shell=expand) + retcode = subprocess.call(real_cmd, *k, **kw) if retcode: raise CalledProcessError(retcode, real_cmd) @@ -723,14 +719,12 @@ def isModeExecChanged(src_mode, dst_mode): return isModeExec(src_mode) != isModeExec(dst_mode) def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False, - errors_as_exceptions=False): + errors_as_exceptions=False, *k, **kw): if not isinstance(cmd, list): cmd = "-G " + cmd - expand = True else: cmd = ["-G"] + cmd - expand = False cmd = p4_build_cmd(cmd) if verbose: @@ -751,10 +745,8 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False, stdin_file.flush() stdin_file.seek(0) - p4 = subprocess.Popen(cmd, - shell=expand, - stdin=stdin_file, - stdout=subprocess.PIPE) + p4 = subprocess.Popen( + cmd, stdin=stdin_file, stdout=subprocess.PIPE, *k, **kw) result = [] try: @@ -807,8 +799,8 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False, return result -def p4Cmd(cmd): - list = p4CmdList(cmd) +def p4Cmd(cmd, *k, **kw): + list = p4CmdList(cmd, *k, **kw) result = {} for entry in list: result.update(entry) @@ -857,7 +849,7 @@ def isValidGitDir(path): return git_dir(path) != None def parseRevision(ref): - return read_pipe("git rev-parse %s" % ref).strip() + return read_pipe("git rev-parse %s" % ref, shell=True).strip() def branchExists(ref): rev = read_pipe(["git", "rev-parse", "-q", "--verify", ref], @@ -969,7 +961,7 @@ def p4BranchesInGit(branchesAreInRemotes=True): else: cmdline += "--branches" - for line in read_pipe_lines(cmdline): + for line in read_pipe_lines(cmdline, shell=True): line = line.strip() # only import to p4/ @@ -1032,7 +1024,7 @@ def createOrUpdateBranchesFromOrigin(localRefPrefix = "refs/remotes/p4/", silent originPrefix = "origin/p4/" - for line in read_pipe_lines("git rev-parse --symbolic --remotes"): + for line in read_pipe_lines("git rev-parse --symbolic --remotes", shell=True): line = line.strip() if (not line.startswith(originPrefix)) or line.endswith("HEAD"): continue @@ -1070,7 +1062,8 @@ def createOrUpdateBranchesFromOrigin(localRefPrefix = "refs/remotes/p4/", silent remoteHead, ','.join(settings['depot-paths']))) if update: - system("git update-ref %s %s" % (remoteHead, originHead)) + system("git update-ref %s %s" % (remoteHead, originHead), + shell=True) def originP4BranchesExist(): return gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master") @@ -1184,7 +1177,7 @@ def getClientSpec(): """Look at the p4 client spec, create a View() object that contains all the mappings, and return it.""" - specList = p4CmdList("client -o") + specList = p4CmdList("client -o", shell=True) if len(specList) != 1: die('Output from "client -o" is %d lines, expecting 1' % len(specList)) @@ -1213,7 +1206,7 @@ def getClientSpec(): def getClientRoot(): """Grab the client directory.""" - output = p4CmdList("client -o") + output = p4CmdList("client -o", shell=True) if len(output) != 1: die('Output from "client -o" is %d lines, expecting 1' % len(output)) @@ -1468,7 +1461,7 @@ def p4UserId(self): if self.myP4UserId: return self.myP4UserId - results = p4CmdList("user -o") + results = p4CmdList("user -o", shell=True) for r in results: if 'User' in r: self.myP4UserId = r['User'] @@ -1493,7 +1486,7 @@ def getUserMapFromPerforceServer(self): self.users = {} self.emails = {} - for output in p4CmdList("users"): + for output in p4CmdList("users", shell=True): if "User" not in output: continue self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" @@ -1691,7 +1684,7 @@ def __init__(self): die("Large file system not supported for git-p4 submit command. Please remove it from config.") def check(self): - if len(p4CmdList("opened ...")) > 0: + if len(p4CmdList("opened ...", shell=True)) > 0: die("You have files opened with perforce! Close them before starting the sync.") def separate_jobs_from_description(self, message): @@ -1795,7 +1788,7 @@ def lastP4Changelist(self): # then gets used to patch up the username in the change. If the same # client spec is being used by multiple processes then this might go # wrong. - results = p4CmdList("client -o") # find the current client + results = p4CmdList("client -o", shell=True) # find the current client client = None for r in results: if 'Client' in r: @@ -1811,7 +1804,7 @@ def lastP4Changelist(self): def modifyChangelistUser(self, changelist, newUser): # fixup the user field of a changelist after it has been submitted. - changes = p4CmdList("change -o %s" % changelist) + changes = p4CmdList("change -o %s" % changelist, shell=True) if len(changes) != 1: die("Bad output from p4 change modifying %s to user %s" % (changelist, newUser)) @@ -1822,7 +1815,7 @@ def modifyChangelistUser(self, changelist, newUser): # p4 does not understand format version 3 and above input = marshal.dumps(c, 2) - result = p4CmdList("change -f -i", stdin=input) + result = p4CmdList("change -f -i", stdin=input, shell=True) for r in result: if 'code' in r: if r['code'] == 'error': @@ -1928,7 +1921,7 @@ def edit_template(self, template_file): if "P4EDITOR" in os.environ and (os.environ.get("P4EDITOR") != ""): editor = os.environ.get("P4EDITOR") else: - editor = read_pipe("git var GIT_EDITOR").strip() + editor = read_pipe("git var GIT_EDITOR", shell=True).strip() system(["sh", "-c", ('%s "$@"' % editor), editor, template_file]) # If the file was not saved, prompt to see if this patch should @@ -1986,7 +1979,9 @@ def applyCommit(self, id): (p4User, gitEmail) = self.p4UserForCommit(id) - diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id)) + diff = read_pipe_lines( + "git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id), + shell=True) filesToAdd = set() filesToChangeType = set() filesToDelete = set() @@ -2122,7 +2117,7 @@ def applyCommit(self, id): # # Apply the patch for real, and do add/delete/+x handling. # - system(applyPatchCmd) + system(applyPatchCmd, shell=True) for f in filesToChangeType: p4_edit(f, "-t", "auto") @@ -3446,7 +3441,7 @@ def getBranchMapping(self): else: command = "branches" - for info in p4CmdList(command): + for info in p4CmdList(command, shell=True): details = p4Cmd(["branch", "-o", info["branch"]]) viewIdx = 0 while "View%s" % viewIdx in details: @@ -3537,7 +3532,9 @@ def gitCommitByP4Change(self, ref, change): while True: if self.verbose: print("trying: earliest %s latest %s" % (earliestCommit, latestCommit)) - next = read_pipe("git rev-list --bisect %s %s" % (latestCommit, earliestCommit)).strip() + next = read_pipe( + "git rev-list --bisect %s %s" % (latestCommit, earliestCommit), + shell=True).strip() if len(next) == 0: if self.verbose: print("argh") @@ -3692,7 +3689,7 @@ def sync_origin_only(self): if self.hasOrigin: if not self.silent: print('Syncing with origin first, using "git fetch origin"') - system("git fetch origin") + system("git fetch origin", shell=True) def importHeadRevision(self, revision): print("Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), revision, self.branch)) @@ -3859,8 +3856,8 @@ def run(self, args): if len(self.branch) == 0: self.branch = self.refPrefix + "master" if gitBranchExists("refs/heads/p4") and self.importIntoRemotes: - system("git update-ref %s refs/heads/p4" % self.branch) - system("git branch -D p4") + system("git update-ref %s refs/heads/p4" % self.branch, shell=True) + system("git branch -D p4", shell=True) # accept either the command-line option, or the configuration variable if self.useClientSpec: @@ -4063,7 +4060,7 @@ def run(self, args): # Cleanup temporary branches created during import if self.tempBranches != []: for branch in self.tempBranches: - read_pipe("git update-ref -d %s" % branch) + read_pipe("git update-ref -d %s" % branch, shell=True) os.rmdir(os.path.join(os.environ.get("GIT_DIR", ".git"), self.tempBranchLocation)) # Create a symbolic ref p4/HEAD pointing to p4/ to allow @@ -4095,7 +4092,7 @@ def run(self, args): def rebase(self): if os.system("git update-index --refresh") != 0: die("Some files in your working directory are modified and different than what is in your index. You can use git update-index to bring the index up to date or stash away all your changes with git stash."); - if len(read_pipe("git diff-index HEAD --")) > 0: + if len(read_pipe("git diff-index HEAD --", shell=True)) > 0: die("You have uncommitted changes. Please commit them before rebasing or stash them away with git stash."); [upstream, settings] = findUpstreamBranchPoint() @@ -4106,9 +4103,10 @@ def rebase(self): upstream = re.sub("~[0-9]+$", "", upstream) print("Rebasing the current branch onto %s" % upstream) - oldHead = read_pipe("git rev-parse HEAD").strip() - system("git rebase %s" % upstream) - system("git diff-tree --stat --summary -M %s HEAD --" % oldHead) + oldHead = read_pipe("git rev-parse HEAD", shell=True).strip() + system("git rebase %s" % upstream, shell=True) + system("git diff-tree --stat --summary -M %s HEAD --" % oldHead, + shell=True) return True class P4Clone(P4Sync): @@ -4185,7 +4183,7 @@ def run(self, args): # auto-set this variable if invoked with --use-client-spec if self.useClientSpec_from_options: - system("git config --bool git-p4.useclientspec true") + system("git config --bool git-p4.useclientspec true", shell=True) return True @@ -4319,7 +4317,7 @@ def run(self, args): cmdline = "git rev-parse --symbolic " cmdline += " --remotes" - for line in read_pipe_lines(cmdline): + for line in read_pipe_lines(cmdline, shell=True): line = line.strip() if not line.startswith('p4/') or line == "p4/HEAD": @@ -4404,9 +4402,11 @@ def main(): cmd.gitdir = os.path.abspath(".git") if not isValidGitDir(cmd.gitdir): # "rev-parse --git-dir" without arguments will try $PWD/.git - cmd.gitdir = read_pipe("git rev-parse --git-dir").strip() + cmd.gitdir = read_pipe( + "git rev-parse --git-dir", shell=True).strip() if os.path.exists(cmd.gitdir): - cdup = read_pipe("git rev-parse --show-cdup").strip() + cdup = read_pipe( + "git rev-parse --show-cdup", shell=True).strip() if len(cdup) > 0: chdir(cdup); From patchwork Thu Jan 6 21:40:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Holdsworth X-Patchwork-Id: 12705750 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00091C433EF for ; Thu, 6 Jan 2022 21:41:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244333AbiAFVlF (ORCPT ); Thu, 6 Jan 2022 16:41:05 -0500 Received: from mail-dm6nam12on2043.outbound.protection.outlook.com ([40.107.243.43]:57313 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S244330AbiAFVlD (ORCPT ); Thu, 6 Jan 2022 16:41:03 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=jamxOJmvUiXWiCULkoiw/DcwDLl00jSBtG4Agxb9zoJSZWNQHbwYYb+kQ4jivhLLh3F/U0RMuuPjqYP7I3VGRxNWy41pYEqyFP2ifGaSSRrumIljYDfiywrNC5yznYzcicVfyjtbE7475mWQ7WfjSmgb44GsSWfmXyVW50Gp9Re8wMGuq1GX/gOh4HOWa0mpT0SiyRf9dpebAqYvcKOhxapWX78hwPt+7/5obJ+2bgCBefLQSH12Y93LVVeCCf9gd9JsBWPImv4kT5yPbAV0Sc2iWWdIMnBLGq08VnuIh9fmfgPvoYKaCW1iU8ORkoSjWORBpiSEO69Xhvf/j1hKdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=9K/MFep3Wo5zdNXsHxqAo0kMmdzYOpR40Saz2fwqmaY=; b=T1wKCRx/CMC97ZH7/KauUwvivL3b2d8oZhsmyCp0FtRd2vGmvWW9kv3yCrzCS1487DvHbZFutn1eTyfeTmyLPTHn2OMpnepT65v/v0CzUEQWpVPH+rcoq4ZgXyrHgDqpcYd/aA+A258tvIoNWo3V9QToYBm1rRH9DYWuSYRYZG0FHPlzsholDMZ/ISwH26OJCvdrVj8KhJXB8VSfFlnzrNSEKVKisH9ZwT1oD9rPrfHF6mJB5EPhHJPH1gk8x7c1j5UBPs36oDyjVigXmssk7cGzF2+qOJ4KLNsWxaFgf3UFERl9Dk/pTkCRkd5/G1BQCCGBe4WjJrgdoUk7z1vXOg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9K/MFep3Wo5zdNXsHxqAo0kMmdzYOpR40Saz2fwqmaY=; b=RA2fa4z3agSFttVlvtX2cVDChFAtGPVmBt2WGRj/nTgI/lfzJabJVaDX+o9EsOg8b/L7D2EJxV3EZHIBsrajBvwlwlvglsYmYab6fhR1Yf8epugVCJWOvCZyYXbH7jG/bF9gNVvHzBUenKMXydK8UmOfnzaQwle6lHuCvfrKZBXc2a9pc1EU1RHI5bwtegs0+Wu1VrSMU0EGsvT/O27QfR/Nd4fWkrXV3Sl+wqZ0593le4cmoTnuKv2B4nAgBDLeb+gqJfN90q9FS8RZV6GLUzihNNfzP/QDcnqGBYbA/7mCLbfzkc7olJBWSRsjUf1ecSOwnqr/mKr3fFfkqiKBYw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from BL0PR12MB4849.namprd12.prod.outlook.com (2603:10b6:208:1c2::17) by MN2PR12MB3854.namprd12.prod.outlook.com (2603:10b6:208:16a::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4867.10; Thu, 6 Jan 2022 21:41:02 +0000 Received: from BL0PR12MB4849.namprd12.prod.outlook.com ([fe80::509e:bbb9:e1fb:26ed]) by BL0PR12MB4849.namprd12.prod.outlook.com ([fe80::509e:bbb9:e1fb:26ed%4]) with mapi id 15.20.4867.009; Thu, 6 Jan 2022 21:41:02 +0000 From: Joel Holdsworth To: git@vger.kernel.org, Luke Diamand , Junio C Hamano , Eric Sunshine Cc: Tzadik Vanderhoof , Dorgon Chang , Joachim Kuebart , Daniel Levin , Johannes Schindelin , Ben Keene , Andrew Oakley , Joel Holdsworth Subject: [PATCH v2 2/3] git-p4: pass command arguments as lists instead of using shell Date: Thu, 6 Jan 2022 21:40:34 +0000 Message-Id: <20220106214035.90725-3-jholdsworth@nvidia.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220106214035.90725-1-jholdsworth@nvidia.com> References: <20220106214035.90725-1-jholdsworth@nvidia.com> X-ClientProxiedBy: AM8P190CA0030.EURP190.PROD.OUTLOOK.COM (2603:10a6:20b:219::35) To BL0PR12MB4849.namprd12.prod.outlook.com (2603:10b6:208:1c2::17) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 59e98c36-b7da-41c5-8ca3-08d9d15d3c2d X-MS-TrafficTypeDiagnostic: MN2PR12MB3854:EE_ X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:462; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: q5xn2Qe0Xb9HJctZ4tjiDLITXu09MHDmtPeOnvu/LdCCdqQkeD3kgA5Zr56ywFU6aYHo4IT2fVXdCxY7eTu5v7MCwcQ5Z4Hzgk+TbrhiHj0hkDZnopicjSrypqqlcSakYci4udZOXjHn4UWWxrYHr1MZXeitw7YhMf/lxBBpTKV4SNnVzXQmcCQG3igDUiQsj1k34rOvskfwiQGZE6OVF42bYxr2AfzwO4+waGDi2McL3Wdrb+ae4m3eN2kzwa60NOSLw2SsVu3WWDotEKfJbssEGdDcwjdPvzroM5W71bQJtB4FnNTwCNHgavZlMTl5PaP02fSnicGWhJpcZZ8em+JPar7nlWz3+G76JUMzJm9vCTJrc99ZyXkq38W6rT1f9A7lyc/KldTaksX79Zc/TTq+FNdN0l/BgShsIlN9haEfoiL0EKqxxpzd2/A/yH+Y9rRU8xOFdC9Ihs8+S6VgjNzNzTlpZcVxiEZrF4cT8Lu/P3/ieKsG8UEuQd8Tg9zMW0GU+Bt9jnfs1aiG0LQt4fTuKDXQKR0/BqQc7bW/fKej9RjY804YsZ6Wqlt8zsUv+PPxH5UyPf2YyptJ40DmbtkoQV4X6oGJp76uqoN7okEJCJDSozMPW82NwGx9ryaZpBrLw9GC8tSAvk7JAyO3fUcfZov8Oc+g7POQpVA6gtGB54BbxQcKKII2PMskUnqtTl8mVDLXV5FN5JbNOjXKfkAdU8QLvDRdmp46ehH7rFM= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BL0PR12MB4849.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(38100700002)(508600001)(26005)(66556008)(66476007)(83380400001)(186003)(4326008)(38350700002)(8936002)(66946007)(8676002)(36756003)(2616005)(7416002)(54906003)(6512007)(6666004)(107886003)(52116002)(2906002)(30864003)(6486002)(316002)(5660300002)(6506007)(110136005)(1076003)(55236004)(86362001)(403724002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: hZm46+hr3VgqBdoEf1ITiRmcnLG2pMJqnMpwa7GEoa/+wcAwkUS0e9YI7Y4G2ImEiUB0eooW2V5rEBuG0sUkCVqRDKO2grCR/Rww6ZtqNMHJVvDqibyaKOeNnZjnN8i+3IC0Xxfen7jdJPZUNQ/omlqVrpVdmQOtGM1awU5O0wPXi9k/YiIXPwsMU6YGS8tCmGqqr9uSZ8uo83SQJS2AqFPAVkgGLE+8MrBzKETAQV4F8ziz0fTzoka+1dPk+cOWckKTt4SZfQw7ptlKthRuZlUnAaUYYRat5PaZSj4Yzr9La1KC7hK1UqrvxgtkJsyfZY5h9wzDQsX2n8nvs1SS8ZxWAYR7aQWzigwITkA9yU+4wVZxOPvhEIDbsSjgMVkB0Rj54Pt8ELHOACuHiOIKdnc1bewZLVqvmUhNzzRsvy4jfl/wPxkEeRj4twDP5Z4TPJy/fTyXf6C6djExAQgXPBMhSJJPiCaqsgp46RLZlFb4fLR+M6PYQbssfWU5C5WgjkUyfQEQVfUKoZ/141i+BQDkBWhNWZASNMBvmfXQ/Zvd72dE9aPNGD5gEo6OgKPOa5hgNKnq3OtK4iIA8/ohFQUQ9aO4n/hlw5RUzau6qOcRqBtVvBjXlF01dQI5LS2AZzaDE45lW4RxMiUkStBp9HAFcBLQQgE2BuudZo1wP8CyesyuWghLD15TdBgaGLHcvANGf6Duhh2DPumatLHjLguhdbuUPci+0EFV5++1/bHqhZwTHauxrSW8t69gl2ysEh6fb6FAE6kbo47rE+Ymqjpp2YlG5cAjmqu1HVXiF/I1sYBSw42Wpn9Pay62qV6OT938QPG7m+CXLTbDRXLKYF+ABPqTpVpjWlWkxYDs07tjH4wbe6c2GLGfqmhDMSRkom6gF5bilph+DDaCPDyKtmDNLxlTrgTC2SKhbZ4ChNTKHnNx0gHyakBRyaCv8CuUx7QxP213BNwlbI6xRU1g8T5Ee2Q7GrMw7r4d47gpKweRTfEcAFftdfSB906Coc5rq75tR0CdpnMRKwUCvwf+vkudQRkGhMt6xg4UrYigYFw+MRlQLKftxHZR8UVC3FiEjdvPMHtOnIhyEgqbsnUdP+D7OV5TcU2R/Krb+v62AT0r2fqJ8Pm6OiBpq3KZhALwDfvIyxbPYLNe5Zi05WsIVYDD7IQ36bIOMH813PGEB1XUKh8VSvKr1p51/Q2yZikYg4/y7v/uS89OwhKNWgQTkemYsZPQeKjm2ptMRWdNaw/V9Ufp3QMZ0/VpWtNUeW8NsTlY2fXH6rJQ2xNzLAPJB+WvEPCx5cekNKOc5iMEG9TRHVBRxo0CwbhG1wPhzPaONSCwv7SI7+KnOxGd1Ytln8jLgyLsE+qGZoPwub1I52/PaHux9/wS7+K/NFDnfSl80ZW2flDAyg1l/sVYiYsnKrzQdhrmMI1XS8EdXi5/z0x1kv+PbptqTxpAuK1P3FCHqpdibpZ+44XAg1XLnO1qqTZO8kXZzQWz1V791PJku73JNC2XpGSGSTISWmhOmjv5FGweJ8NuhjaW5PBrIqLoYvpPycyEyVPFo4jOn6JMp7XqZvg7Qdn5egZlJXYY3DwzarQbcNXp5x4Xf3JBvDni9lt9zkGIiauzN5sFLyMols4= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 59e98c36-b7da-41c5-8ca3-08d9d15d3c2d X-MS-Exchange-CrossTenant-AuthSource: BL0PR12MB4849.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Jan 2022 21:41:02.3448 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: zN4F2OPBBJdwN4yCGNthYbIDKVUU+2TnrUGycxi2ZIWVoany7vgiDEg7Vv2EbkRFpeQ+Z7UBJIfjKJsvrW9Dlg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB3854 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org In the majority of the subprocess calls where shell=True was used, it was only needed to parse command arguments by spaces. In each of these cases, the commands are now being passed in as lists instead of strings. This change aids the comprehensibility of the code. Constucting commands and arguments using strings risks bugs from unsanitized inputs, and the attendant complexity of properly quoting and escaping command arguments. Signed-off-by: Joel Holdsworth --- git-p4.py | 105 ++++++++++++++++++++++-------------------------------- 1 file changed, 43 insertions(+), 62 deletions(-) diff --git a/git-p4.py b/git-p4.py index 7ec90388b6..492eb5aa23 100755 --- a/git-p4.py +++ b/git-p4.py @@ -96,10 +96,7 @@ def p4_build_cmd(cmd): # Provide a way to not pass this option by setting git-p4.retries to 0 real_cmd += ["-r", str(retries)] - if not isinstance(cmd, list): - real_cmd = ' '.join(real_cmd) + ' ' + cmd - else: - real_cmd += cmd + real_cmd += cmd # now check that we can actually talk to the server global p4_access_checked @@ -721,12 +718,7 @@ def isModeExecChanged(src_mode, dst_mode): def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False, errors_as_exceptions=False, *k, **kw): - if not isinstance(cmd, list): - cmd = "-G " + cmd - else: - cmd = ["-G"] + cmd - - cmd = p4_build_cmd(cmd) + cmd = p4_build_cmd(["-G"] + cmd) if verbose: sys.stderr.write("Opening pipe: %s\n" % str(cmd)) @@ -849,7 +841,7 @@ def isValidGitDir(path): return git_dir(path) != None def parseRevision(ref): - return read_pipe("git rev-parse %s" % ref, shell=True).strip() + return read_pipe(["git", "rev-parse", ref]).strip() def branchExists(ref): rev = read_pipe(["git", "rev-parse", "-q", "--verify", ref], @@ -955,13 +947,13 @@ def p4BranchesInGit(branchesAreInRemotes=True): branches = {} - cmdline = "git rev-parse --symbolic " + cmdline = ["git", "rev-parse", "--symbolic"] if branchesAreInRemotes: - cmdline += "--remotes" + cmdline.append("--remotes") else: - cmdline += "--branches" + cmdline.append("--branches") - for line in read_pipe_lines(cmdline, shell=True): + for line in read_pipe_lines(cmdline): line = line.strip() # only import to p4/ @@ -1024,7 +1016,7 @@ def createOrUpdateBranchesFromOrigin(localRefPrefix = "refs/remotes/p4/", silent originPrefix = "origin/p4/" - for line in read_pipe_lines("git rev-parse --symbolic --remotes", shell=True): + for line in read_pipe_lines(["git", "rev-parse", "--symbolic", "--remotes"]): line = line.strip() if (not line.startswith(originPrefix)) or line.endswith("HEAD"): continue @@ -1062,8 +1054,7 @@ def createOrUpdateBranchesFromOrigin(localRefPrefix = "refs/remotes/p4/", silent remoteHead, ','.join(settings['depot-paths']))) if update: - system("git update-ref %s %s" % (remoteHead, originHead), - shell=True) + system(["git", "update-ref", remoteHead, originHead]) def originP4BranchesExist(): return gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master") @@ -1177,7 +1168,7 @@ def getClientSpec(): """Look at the p4 client spec, create a View() object that contains all the mappings, and return it.""" - specList = p4CmdList("client -o", shell=True) + specList = p4CmdList(["client", "-o"]) if len(specList) != 1: die('Output from "client -o" is %d lines, expecting 1' % len(specList)) @@ -1206,7 +1197,7 @@ def getClientSpec(): def getClientRoot(): """Grab the client directory.""" - output = p4CmdList("client -o", shell=True) + output = p4CmdList(["client", "-o"]) if len(output) != 1: die('Output from "client -o" is %d lines, expecting 1' % len(output)) @@ -1461,7 +1452,7 @@ def p4UserId(self): if self.myP4UserId: return self.myP4UserId - results = p4CmdList("user -o", shell=True) + results = p4CmdList(["user", "-o"]) for r in results: if 'User' in r: self.myP4UserId = r['User'] @@ -1486,7 +1477,7 @@ def getUserMapFromPerforceServer(self): self.users = {} self.emails = {} - for output in p4CmdList("users", shell=True): + for output in p4CmdList(["users"]): if "User" not in output: continue self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" @@ -1684,7 +1675,7 @@ def __init__(self): die("Large file system not supported for git-p4 submit command. Please remove it from config.") def check(self): - if len(p4CmdList("opened ...", shell=True)) > 0: + if len(p4CmdList(["opened", "..."])) > 0: die("You have files opened with perforce! Close them before starting the sync.") def separate_jobs_from_description(self, message): @@ -1788,7 +1779,7 @@ def lastP4Changelist(self): # then gets used to patch up the username in the change. If the same # client spec is being used by multiple processes then this might go # wrong. - results = p4CmdList("client -o", shell=True) # find the current client + results = p4CmdList(["client", "-o"]) # find the current client client = None for r in results: if 'Client' in r: @@ -1804,7 +1795,7 @@ def lastP4Changelist(self): def modifyChangelistUser(self, changelist, newUser): # fixup the user field of a changelist after it has been submitted. - changes = p4CmdList("change -o %s" % changelist, shell=True) + changes = p4CmdList(["change", "-o", changelist]) if len(changes) != 1: die("Bad output from p4 change modifying %s to user %s" % (changelist, newUser)) @@ -1815,7 +1806,7 @@ def modifyChangelistUser(self, changelist, newUser): # p4 does not understand format version 3 and above input = marshal.dumps(c, 2) - result = p4CmdList("change -f -i", stdin=input, shell=True) + result = p4CmdList(["change", "-f", "-i"], stdin=input) for r in result: if 'code' in r: if r['code'] == 'error': @@ -1921,7 +1912,7 @@ def edit_template(self, template_file): if "P4EDITOR" in os.environ and (os.environ.get("P4EDITOR") != ""): editor = os.environ.get("P4EDITOR") else: - editor = read_pipe("git var GIT_EDITOR", shell=True).strip() + editor = read_pipe(["git", "var", "GIT_EDITOR"]).strip() system(["sh", "-c", ('%s "$@"' % editor), editor, template_file]) # If the file was not saved, prompt to see if this patch should @@ -1980,8 +1971,7 @@ def applyCommit(self, id): (p4User, gitEmail) = self.p4UserForCommit(id) diff = read_pipe_lines( - "git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id), - shell=True) + ["git", "diff-tree", "-r"] + self.diffOpts + ["{}^".format(id), id]) filesToAdd = set() filesToChangeType = set() filesToDelete = set() @@ -2467,17 +2457,17 @@ def run(self, args): # if self.detectRenames: # command-line -M arg - self.diffOpts = "-M" + self.diffOpts = ["-M"] else: # If not explicitly set check the config variable detectRenames = gitConfig("git-p4.detectRenames") if detectRenames.lower() == "false" or detectRenames == "": - self.diffOpts = "" + self.diffOpts = [] elif detectRenames.lower() == "true": - self.diffOpts = "-M" + self.diffOpts = ["-M"] else: - self.diffOpts = "-M%s" % detectRenames + self.diffOpts = ["-M{}".format(detectRenames)] # no command-line arg for -C or --find-copies-harder, just # config variables @@ -2485,12 +2475,12 @@ def run(self, args): if detectCopies.lower() == "false" or detectCopies == "": pass elif detectCopies.lower() == "true": - self.diffOpts += " -C" + self.diffOpts.append("-C") else: - self.diffOpts += " -C%s" % detectCopies + self.diffOpts.append("-C{}".format(detectCopies)) if gitConfigBool("git-p4.detectCopiesHarder"): - self.diffOpts += " --find-copies-harder" + self.diffOpts.append("--find-copies-harder") num_shelves = len(self.update_shelve) if num_shelves > 0 and num_shelves != len(commits): @@ -3436,12 +3426,9 @@ def getBranchMapping(self): lostAndFoundBranches = set() user = gitConfig("git-p4.branchUser") - if len(user) > 0: - command = "branches -u %s" % user - else: - command = "branches" - for info in p4CmdList(command, shell=True): + for info in p4CmdList( + ["branches"] + (["-u", user] if len(user) > 0 else [])): details = p4Cmd(["branch", "-o", info["branch"]]) viewIdx = 0 while "View%s" % viewIdx in details: @@ -3532,9 +3519,8 @@ def gitCommitByP4Change(self, ref, change): while True: if self.verbose: print("trying: earliest %s latest %s" % (earliestCommit, latestCommit)) - next = read_pipe( - "git rev-list --bisect %s %s" % (latestCommit, earliestCommit), - shell=True).strip() + next = read_pipe(["git", "rev-list", "--bisect", + latestCommit, earliestCommit]).strip() if len(next) == 0: if self.verbose: print("argh") @@ -3689,7 +3675,7 @@ def sync_origin_only(self): if self.hasOrigin: if not self.silent: print('Syncing with origin first, using "git fetch origin"') - system("git fetch origin", shell=True) + system(["git", "fetch", "origin"]) def importHeadRevision(self, revision): print("Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), revision, self.branch)) @@ -3856,8 +3842,8 @@ def run(self, args): if len(self.branch) == 0: self.branch = self.refPrefix + "master" if gitBranchExists("refs/heads/p4") and self.importIntoRemotes: - system("git update-ref %s refs/heads/p4" % self.branch, shell=True) - system("git branch -D p4", shell=True) + system(["git", "update-ref", self.branch, "refs/heads/p4"]) + system(["git", "branch", "-D", "p4"]) # accept either the command-line option, or the configuration variable if self.useClientSpec: @@ -4060,7 +4046,7 @@ def run(self, args): # Cleanup temporary branches created during import if self.tempBranches != []: for branch in self.tempBranches: - read_pipe("git update-ref -d %s" % branch, shell=True) + read_pipe(["git", "update-ref", "-d", branch]) os.rmdir(os.path.join(os.environ.get("GIT_DIR", ".git"), self.tempBranchLocation)) # Create a symbolic ref p4/HEAD pointing to p4/ to allow @@ -4092,7 +4078,7 @@ def run(self, args): def rebase(self): if os.system("git update-index --refresh") != 0: die("Some files in your working directory are modified and different than what is in your index. You can use git update-index to bring the index up to date or stash away all your changes with git stash."); - if len(read_pipe("git diff-index HEAD --", shell=True)) > 0: + if len(read_pipe(["git", "diff-index", "HEAD", "--"])) > 0: die("You have uncommitted changes. Please commit them before rebasing or stash them away with git stash."); [upstream, settings] = findUpstreamBranchPoint() @@ -4103,10 +4089,10 @@ def rebase(self): upstream = re.sub("~[0-9]+$", "", upstream) print("Rebasing the current branch onto %s" % upstream) - oldHead = read_pipe("git rev-parse HEAD", shell=True).strip() - system("git rebase %s" % upstream, shell=True) - system("git diff-tree --stat --summary -M %s HEAD --" % oldHead, - shell=True) + oldHead = read_pipe(["git", "rev-parse", "HEAD"]).strip() + system(["git", "rebase", upstream]) + system(["git", "diff-tree", "--stat", "--summary", "-M", oldHead, + "HEAD", "--"]) return True class P4Clone(P4Sync): @@ -4183,7 +4169,7 @@ def run(self, args): # auto-set this variable if invoked with --use-client-spec if self.useClientSpec_from_options: - system("git config --bool git-p4.useclientspec true", shell=True) + system(["git", "config", "--bool", "git-p4.useclientspec", "true"]) return True @@ -4314,10 +4300,7 @@ def run(self, args): if originP4BranchesExist(): createOrUpdateBranchesFromOrigin() - cmdline = "git rev-parse --symbolic " - cmdline += " --remotes" - - for line in read_pipe_lines(cmdline, shell=True): + for line in read_pipe_lines(["git", "rev-parse", "--symbolic", "--remotes"]): line = line.strip() if not line.startswith('p4/') or line == "p4/HEAD": @@ -4402,11 +4385,9 @@ def main(): cmd.gitdir = os.path.abspath(".git") if not isValidGitDir(cmd.gitdir): # "rev-parse --git-dir" without arguments will try $PWD/.git - cmd.gitdir = read_pipe( - "git rev-parse --git-dir", shell=True).strip() + cmd.gitdir = read_pipe(["git", "rev-parse", "--git-dir"]).strip() if os.path.exists(cmd.gitdir): - cdup = read_pipe( - "git rev-parse --show-cdup", shell=True).strip() + cdup = read_pipe(["git", "rev-parse", "--show-cdup"]).strip() if len(cdup) > 0: chdir(cdup); From patchwork Thu Jan 6 21:40:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Holdsworth X-Patchwork-Id: 12705751 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B9525C433EF for ; Thu, 6 Jan 2022 21:41:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244338AbiAFVlK (ORCPT ); Thu, 6 Jan 2022 16:41:10 -0500 Received: from mail-bn8nam12on2066.outbound.protection.outlook.com ([40.107.237.66]:4961 "EHLO NAM12-BN8-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S244184AbiAFVlF (ORCPT ); Thu, 6 Jan 2022 16:41:05 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mU1uHB09uRhhhEziVO48qlAagW4uz3inbdJvzeHxeOTOERGRodu1JFKp+uK3X2PNDFSqB6bnxnPe6I1ZSruG+DRZmlqdZFraww/rD6RkTDHpzCKPOBzhg7MXxLjuQ3YTXM5n5XxiMImyAjII8KCD6Fq9zjMtxkDvRyl/z55RRGixitQ4Tu5AuIa0QGBk7/A7Vdk/+oo2jE26uPHEupqY9zDgtZOui55PioK+GEpmoFrsqfvP4IOcFlyU1wXSNSXPwtMt97peG6EH6RoGDkd/vpgoKXi5NL1V2AZgVUuTYUwlU51i5/3AX//BlfgWhSF8g1MLgtsi9Wh0LtXpT6SyEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=VEhenfocq+zuQEaWBFZ05uLkfKy/efnxBvZbC4t7h9c=; b=bfgPFsHKDxIlHBoaE0cbmnAR1tgWlRJus3Aw6lDzkTt1B+HtvYyxmyr+UlDenf/zrD8KCVB1wK35rFhetihXjnrIQi7/L5172Q2x2ta8chLrzQIRn5T5S/nrwlI95VwRqCuf7IvIvtwhwYnd2JKadm5lGyWhnrq30V7t85xXSMNPOQBPt+RVqxx4q5gUbq1IkV5Tu8OEljcroBG5zxiqWgjo8kwZGYL9EcKY2V5n2HDDUQwGSNX4Ye38ZURjTPMaLQtSqgifOTg3U3GYIjq2Bdeve9j98dMjxqcrXEsf+APirzmBxRkcpUC9De5eob/Bl5a7B5Za2F7xHkPvz+LCyw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=VEhenfocq+zuQEaWBFZ05uLkfKy/efnxBvZbC4t7h9c=; b=PqBXtXPw5iK0s908gTrLGoVUa+Mh+hZ8HcrjupgNXWGuj6w6rcdSrTfLy//Gp9dtvkyXD5LOJQJcKZa3TSAs6WJhPVKhtBgFKTvLsFpxcD/GwimrDa3ntwwqrOqAbrBKWJ89HQ83jJUctVI34sfWX2Y5ajlu1cUdRr5CWbWVL+FtaeDSa2tGe18ia832YH060DbkDwKcP5KJNyL9PNR+mlve+PwQTt0VxrX65LXLzeQyF5QFgnumhXvKzxN4kG2QmNA+p7Y+2Qic5l53fs7UVRi/lEv2iLSM9n5mF+7qT9bK7lFMPs5RTGOap/lt7u/yv1bIGJWjGzAZk6CL4k6Baw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from BL0PR12MB4849.namprd12.prod.outlook.com (2603:10b6:208:1c2::17) by MN2PR12MB3854.namprd12.prod.outlook.com (2603:10b6:208:16a::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4867.10; Thu, 6 Jan 2022 21:41:04 +0000 Received: from BL0PR12MB4849.namprd12.prod.outlook.com ([fe80::509e:bbb9:e1fb:26ed]) by BL0PR12MB4849.namprd12.prod.outlook.com ([fe80::509e:bbb9:e1fb:26ed%4]) with mapi id 15.20.4867.009; Thu, 6 Jan 2022 21:41:04 +0000 From: Joel Holdsworth To: git@vger.kernel.org, Luke Diamand , Junio C Hamano , Eric Sunshine Cc: Tzadik Vanderhoof , Dorgon Chang , Joachim Kuebart , Daniel Levin , Johannes Schindelin , Ben Keene , Andrew Oakley , Joel Holdsworth Subject: [PATCH v2 3/3] git-p4: don't print shell commands as python lists Date: Thu, 6 Jan 2022 21:40:35 +0000 Message-Id: <20220106214035.90725-4-jholdsworth@nvidia.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220106214035.90725-1-jholdsworth@nvidia.com> References: <20220106214035.90725-1-jholdsworth@nvidia.com> X-ClientProxiedBy: AM8P190CA0030.EURP190.PROD.OUTLOOK.COM (2603:10a6:20b:219::35) To BL0PR12MB4849.namprd12.prod.outlook.com (2603:10b6:208:1c2::17) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5a4fbb28-d1cb-4a68-2687-08d9d15d3d74 X-MS-TrafficTypeDiagnostic: MN2PR12MB3854:EE_ X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:1751; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: wQCimdJbfNSyGo4OlxIZoCsmFbI69N+rRW9rUNDyIz5LW22hSnemkJgSanfaeMzX4eVeVPLpP1koBAPEpJT/SXcloOaQHuwqS+rt0QX9KPu4HybpshVYSNelPW71p/+yLYOuvcPs3qnD4bxbqtoZchRum7b+as85PTdPxO1ItUDjeS+vzz6PwHZqSpx3v7k7YUA1Vt/noQN1VbJgibmqXBnFYGBf2RLNDm52UHLk3i3DtRUl48ovxiwYjXsW3vdAxPR3GVxtmrGipTL/+1BZamnn/qBS41sc+dy7Zi9zFSWBBdi0dM8tgOt8Faddis5kUcFfY78TOxIwCb+/H4dg2Vax5YrhxPT4+ooNXnYdpiVlhw6xMEoB1Vg9BgmNglefEwniGlWMwfPRQCWkKjjrsFngfzBzYFealYNahZMNDmOoAiFXppm2pE5Ixi9aWgSmgpUB6AFt9+L/7kr5uQ3URVveSSr9TvJTpNmZ65uVdWTzE+feAtSUvI89kLJdYzQwdNYLTWW98eWJFTMFvbxkgfnjSECuuiYxdgR805DOFvANRXF/QRQIRbUcSO4nGcPvO53978p5fR+4m2ssmWJ5bmm/I48SZoJbBB+F7VAFq7bVurDDm2iV00CcI5XbD7E6Tw7MN3z71NmOTUV9//cLuewjd6xGw1ggFQPl3j4xfnkCHNpIDNUZ0W4rBplX0g/pt8yA9271O36ExQW53xD+iQ== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BL0PR12MB4849.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(38100700002)(508600001)(26005)(66556008)(66476007)(83380400001)(186003)(4326008)(38350700002)(8936002)(66946007)(8676002)(36756003)(2616005)(7416002)(54906003)(6512007)(6666004)(107886003)(52116002)(2906002)(6486002)(316002)(5660300002)(6506007)(110136005)(1076003)(55236004)(86362001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: ZNAGhwOfRPpXsFpqTO49yyqaTwvfkegL8IKFex4wmSIYtECjjh4Qh38qvXew1tno8uwFeg90HQFiZ2JQVqfFXr+XfCNtRbgQSx9l0T27oBn1Gda+NGWtkhfMQ/jrCfyNb5JGDOEiAa/pRcBS/sK7RMd3L5hz2vkoTNm5GxYFvYBhA1aaXGHaxnhb5L7iZmlvf7TO9JDNHtTioomKaFIEarpLSAtuKI7+ojlfKIpXUVO0rgiWZKVsGuNO1FgBHPEoZBnGEdYrh0HZpOhnChQbbntG8cYIeRrvnLN2CLM27/wqVkox0Fsc2n0sZOT8fty2u5G4XypWGu+1HCz529x7/QM9/CSuc264Rx8h8ANhiZATKvN5wjU/ee5wFpOQPaFE30hRBz/KK0jmC/c79csZzKG3ETDEfCuzTiwqthufu+QBm8MdGqdQ5f2yGd3q2zDyC9bn+TidrBEWduGEmjH/yPIo2YNbXykae0KZ7wq0qAXe5U3h+wGvofgDi5SH861gebbHvyut0VnrtnAwnB5n5OM2FQhZPeQ8YhaLpZJR9PYwyE2Lvc5cfttEdKDHWelIH7gJPocthvvZC9HhDJwiZAOc4CHOED9Q8205P9EWjAgKAJ/EB4VOmAMhQBssx+IXG/OrIw/DuU7qb5Y4mHgsbfe5yu+3TGEcLl0bn7Q2v/MnMaMm0I5fz9zWz/PtkHg9+uWuF1NFQCKyShJg8pMEQqlizZhTb7OJBuwOJIfGdSumgHem/irJxGaimyeP2JgPjWYUwiH2k93kCpEZws1YGf0LcQO5p3OAE2exH9oqKVZ2gfZe2wGSj3zyNBZwXIabTIhKUmcAVE+6xWZvgDv5t9X69Umz91xSz0AAjTcCj2fHK4CIMIj6RuJXTpTVxUo9FIy4+zcMuowOXDKRAeRRt6MdJuKrxZRDdcjy7Auv7gee+PGhTqRKF/IiXk2pDMbIrlGQfaDIsWVc32tu4N3sHwTb6cFqfmrx/mwKDX+ZQ8skiMinDHh/9CB2lacm6MGLNxoQ7sa6x7eWhV6GNRMJKLoteJb8dUPe0JiygaqbNOc0tIKnVFCJQ1jAalm4ElWzQ4DEu8afMLbPF9Zl1l6KvbA/M5YREM8H9reD56nQGlFvcPlAxDMd+6yEm0eJ81xrssfABiez3cZJDFa5/QC5JrEJaTlCelkUyzhirkmPFdOsy6W3sk5FBdJDI/SzUx/R2xYLAAPKu3/wwsqdsIkScOi2cSyzUGdmB8oHU7950nGnJK9+jbihhZKaWzPcpzLnFdNak9CUDUbE6fnX2N1syO/Lwa+SkLz1ITayL3BeCCPs50Dx3x0U4a8UwMMgvsmDbsQi0uHOfWhKbYSowiIFXe602hTK942wQEZ0JdzR7AG+XAavfvUnObVrMZbX5vIsfPliPN43mBWK4xrCtjTnt4kivm8GhoGzn7wvKg70uPW59ZNg//r63ob1KjTqrCks6twtxyDLe4/UijuxGEdAO3A832aQFggBdtwN/2zLI+67PQuK4RzXXjwFkBq5QcZUoW97qKHfT9aMKSkd7vxaHkCf70564zPyVRXjMmBCUXztAflQUyhxtSIQx1xBXkxoN47s8dffF2R1mEQ/swFhNteYEMNujdDTYvP4DkUnaD8= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5a4fbb28-d1cb-4a68-2687-08d9d15d3d74 X-MS-Exchange-CrossTenant-AuthSource: BL0PR12MB4849.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Jan 2022 21:41:04.4866 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: nkxu/NgxBcLzNG8MLefwek+BoJY+DElHo5Px5jKJ0xnfFCnJUFmcdJ0/wMG03nxhRl41o9OUM4e8em8j4Ue/3g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB3854 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Previously the git-p4 script would log commands as stringified representations of the command parameter, leading to output such as this: Reading pipe: ['git', 'config', '--bool', 'git-p4.useclientspec'] Now that all commands are list objects, this patch instead joins the elements of the list into a single string so the output now looks more readable: Reading pipe: git config --bool git-p4.useclientspec Signed-off-by: Joel Holdsworth --- This corrects a typo in the commit message. git-p4.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/git-p4.py b/git-p4.py index 492eb5aa23..465ed16b25 100755 --- a/git-p4.py +++ b/git-p4.py @@ -275,14 +275,14 @@ def run_hook_command(cmd, param): def write_pipe(c, stdin, *k, **kw): if verbose: - sys.stderr.write('Writing pipe: %s\n' % str(c)) + sys.stderr.write('Writing pipe: {}\n'.format(' '.join(c))) p = subprocess.Popen(c, stdin=subprocess.PIPE, *k, **kw) pipe = p.stdin val = pipe.write(stdin) pipe.close() if p.wait(): - die('Command failed: %s' % str(c)) + die('Command failed: {}'.format(' '.join(c))) return val @@ -298,7 +298,7 @@ def read_pipe_full(c, *k, **kw): text. """ if verbose: - sys.stderr.write('Reading pipe: %s\n' % str(c)) + sys.stderr.write('Reading pipe: {}\n'.format(' '.join(c))) p = subprocess.Popen( c, stdout=subprocess.PIPE, stderr=subprocess.PIPE, *k, **kw) @@ -317,7 +317,7 @@ def read_pipe(c, ignore_error=False, raw=False, *k, **kw): if ignore_error: out = "" else: - die('Command failed: %s\nError: %s' % (str(c), err)) + die('Command failed: {}\nError: {}'.format(' '.join(c), err)) if not raw: out = decode_text_stream(out) return out @@ -338,7 +338,7 @@ def p4_read_pipe(c, ignore_error=False, raw=False, *k, **kw): def read_pipe_lines(c, raw=False, *k, **kw): if verbose: - sys.stderr.write('Reading pipe: %s\n' % str(c)) + sys.stderr.write('Reading pipe: {}\n'.format(' '.join(c))) p = subprocess.Popen(c, stdout=subprocess.PIPE, *k, **kw) pipe = p.stdout @@ -346,7 +346,7 @@ def read_pipe_lines(c, raw=False, *k, **kw): if not raw: lines = [decode_text_stream(line) for line in lines] if pipe.close() or p.wait(): - die('Command failed: %s' % str(c)) + die('Command failed: {}'.format(' '.join(c))) return lines def p4_read_pipe_lines(c, *k, **kw): @@ -385,7 +385,8 @@ def p4_has_move_command(): def system(cmd, ignore_error=False, *k, **kw): if verbose: - sys.stderr.write("executing %s\n" % str(cmd)) + sys.stderr.write("executing {}\n".format( + ' '.join(cmd) if isinstance(cmd, list) else cmd)) retcode = subprocess.call(cmd, *k, **kw) if retcode and not ignore_error: raise CalledProcessError(retcode, cmd) @@ -720,7 +721,7 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False, cmd = p4_build_cmd(["-G"] + cmd) if verbose: - sys.stderr.write("Opening pipe: %s\n" % str(cmd)) + sys.stderr.write("Opening pipe: {}\n".format(' '.join(cmd))) # Use a temporary file to avoid deadlocks without # subprocess.communicate(), which would put another copy