From 9030b1a9ede997a0bed1a1d0bc1e0a957a236992 Mon Sep 17 00:00:00 2001
From: Amos Wenger <fasterthanlime@users.noreply.github.com>
Date: Wed, 27 Oct 2021 12:03:32 +0200
Subject: [PATCH] feat(cargo): Use --workspace for crate updating (#12334)

---
 .../__snapshots__/artifacts.spec.ts.snap      | 10 ++---
 lib/manager/cargo/artifacts.ts                | 42 ++++---------------
 2 files changed, 12 insertions(+), 40 deletions(-)

diff --git a/lib/manager/cargo/__snapshots__/artifacts.spec.ts.snap b/lib/manager/cargo/__snapshots__/artifacts.spec.ts.snap
index babdcd777c..c063131c28 100644
--- a/lib/manager/cargo/__snapshots__/artifacts.spec.ts.snap
+++ b/lib/manager/cargo/__snapshots__/artifacts.spec.ts.snap
@@ -3,7 +3,7 @@
 exports[`manager/cargo/artifacts returns null if unchanged 1`] = `
 Array [
   Object {
-    "cmd": "cargo update --manifest-path Cargo.toml --package dep1",
+    "cmd": "cargo update --manifest-path Cargo.toml --workspace",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -26,7 +26,7 @@ Array [
 exports[`manager/cargo/artifacts returns updated Cargo.lock 1`] = `
 Array [
   Object {
-    "cmd": "cargo update --manifest-path Cargo.toml --package dep1",
+    "cmd": "cargo update --manifest-path Cargo.toml --workspace",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -84,7 +84,7 @@ Array [
     },
   },
   Object {
-    "cmd": "docker run --rm --name=renovate_rust --label=renovate_child -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -w \\"/tmp/github/some/repo\\" renovate/rust bash -l -c \\"cargo update --manifest-path Cargo.toml --package dep1\\"",
+    "cmd": "docker run --rm --name=renovate_rust --label=renovate_child -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -w \\"/tmp/github/some/repo\\" renovate/rust bash -l -c \\"cargo update --manifest-path Cargo.toml --workspace\\"",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -107,7 +107,7 @@ Array [
 exports[`manager/cargo/artifacts returns updated workspace Cargo.lock 1`] = `
 Array [
   Object {
-    "cmd": "cargo update --manifest-path crates/one/Cargo.toml --package dep1",
+    "cmd": "cargo update --manifest-path crates/one/Cargo.toml --workspace",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
@@ -130,7 +130,7 @@ Array [
 exports[`manager/cargo/artifacts updates Cargo.lock based on the lookupName, when given 1`] = `
 Array [
   Object {
-    "cmd": "cargo update --manifest-path Cargo.toml --package dep1",
+    "cmd": "cargo update --manifest-path Cargo.toml --workspace",
     "options": Object {
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
diff --git a/lib/manager/cargo/artifacts.ts b/lib/manager/cargo/artifacts.ts
index 6898b9d4b9..1788c8d18c 100644
--- a/lib/manager/cargo/artifacts.ts
+++ b/lib/manager/cargo/artifacts.ts
@@ -7,16 +7,17 @@ import {
   readLocalFile,
   writeLocalFile,
 } from '../../util/fs';
-import { regEx } from '../../util/regex';
 import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
 
 async function cargoUpdate(
   manifestPath: string,
-  packageName?: string
+  isLockFileMaintenance: boolean
 ): Promise<void> {
   let cmd = `cargo update --manifest-path ${quote(manifestPath)}`;
-  if (packageName) {
-    cmd += ` --package ${quote(packageName)}`;
+  // If we're updating a specific crate, `cargo-update` requires `--workspace`
+  // for more information, see: https://github.com/renovatebot/renovate/issues/12332
+  if (!isLockFileMaintenance) {
+    cmd += ` --workspace`;
   }
 
   const execOptions: ExecOptions = {
@@ -24,28 +25,7 @@ async function cargoUpdate(
       image: 'rust',
     },
   };
-  try {
-    await exec(cmd, execOptions);
-  } catch (err) /* istanbul ignore next */ {
-    // Two different versions of one dependency can be present in the same
-    // crate, and when that happens an attempt to update it with --package ${dep}
-    // key results in cargo exiting with error code `101` and an error message:
-    // "error: There are multiple `${dep}` packages in your project".
-    //
-    // If exception `err` was caused by this, we execute `updateAll` function
-    // instead of returning an error. `updateAll` function just executes
-    // "cargo update --manifest-path ${localPackageFileName}" without the `--package` key.
-    //
-    // If exception `err` was not caused by this, we just rethrow it. It will be caught
-    // by the outer try { } catch {} and processed normally.
-    const msgStart = 'error: There are multiple';
-    if (err.code === 101 && err.stderr.startsWith(msgStart)) {
-      cmd = cmd.replace(regEx(/ --package.*/), '');
-      await exec(cmd, execOptions);
-    } else {
-      throw err; // this is caught below
-    }
-  }
+  await exec(cmd, execOptions);
 }
 
 export async function updateArtifacts({
@@ -83,15 +63,7 @@ export async function updateArtifacts({
   try {
     await writeLocalFile(packageFileName, newPackageFileContent);
     logger.debug('Updating ' + lockFileName);
-    for (let i = 0; i < updatedDeps.length; i += 1) {
-      const dep = updatedDeps[i];
-      // Update dependency `${dep}` in Cargo.lock file corresponding to Cargo.toml file located
-      // at ${localPackageFileName} path
-      await cargoUpdate(packageFileName, dep.lookupName ?? dep.depName);
-    }
-    if (isLockFileMaintenance) {
-      await cargoUpdate(packageFileName);
-    }
+    await cargoUpdate(packageFileName, isLockFileMaintenance);
     logger.debug('Returning updated Cargo.lock');
     const newCargoLockContent = await readLocalFile(lockFileName);
     if (existingLockFileContent === newCargoLockContent) {
-- 
GitLab