From 9c9da57aebaa8cb02a27f6501aee6a080520ed06 Mon Sep 17 00:00:00 2001 From: Yim Lee Date: Mon, 14 Aug 2023 16:50:07 -0700 Subject: [PATCH] [netrc] Use the most recent match for auth Motivation: We update `netrc` by appending new entry to the end of the file (we don't delete or modify existing entries). This means when we look for entries matching a given host in the `netrc` file, we should use the _last_ match for the most recent entry. Modification: Check `netrc` lookup to use `last` instead of `first` match. --- Sources/Basics/AuthorizationProvider.swift | 7 ++++++- Tests/BasicsTests/AuthorizationProviderTests.swift | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Sources/Basics/AuthorizationProvider.swift b/Sources/Basics/AuthorizationProvider.swift index a2b28b77556..4335b32146b 100644 --- a/Sources/Basics/AuthorizationProvider.swift +++ b/Sources/Basics/AuthorizationProvider.swift @@ -134,14 +134,19 @@ public class NetrcAuthorizationProvider: AuthorizationProvider, AuthorizationWri } private func machine(for url: URL) -> Basics.Netrc.Machine? { + // Since updates are appended to the end of the file, we + // take the _last_ match to use the most recent entry. if let machine = Self.machine(for: url), - let existing = self.machines.first(where: { $0.name.lowercased() == machine }) + let existing = self.machines.last(where: { $0.name.lowercased() == machine }) { return existing } + + // No match found. Use the first default if any. if let existing = self.machines.first(where: { $0.isDefault }) { return existing } + return .none } diff --git a/Tests/BasicsTests/AuthorizationProviderTests.swift b/Tests/BasicsTests/AuthorizationProviderTests.swift index 3c17b9cc6b1..93fc9bf7cc4 100644 --- a/Tests/BasicsTests/AuthorizationProviderTests.swift +++ b/Tests/BasicsTests/AuthorizationProviderTests.swift @@ -55,14 +55,14 @@ final class AuthorizationProviderTests: XCTestCase { }) // .netrc file now contains two entries for `url`: one with `password` and the other with `newPassword`. - // `NetrcAuthorizationProvider` returns the first entry it finds. - self.assertAuthentication(provider, for: url, expected: (user, password)) + // `NetrcAuthorizationProvider` returns the last entry it finds. + self.assertAuthentication(provider, for: url, expected: (user, newPassword)) - // Make sure the new entry is saved + // Make sure the previous entry is still there XCTAssertNotNil( - provider.machines - .first(where: { $0.name == url.host!.lowercased() && $0.login == user && $0.password == newPassword - }) + provider.machines.first(where: { + $0.name == url.host!.lowercased() && $0.login == user && $0.password == password + }) ) self.assertAuthentication(provider, for: otherURL, expected: (user, otherPassword))