Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid name collision on fetching with appending the hash value of a dependency #2185

Closed
wants to merge 3 commits into from

Conversation

ikesyo
Copy link
Member

@ikesyo ikesyo commented Sep 28, 2017

@ikesyo ikesyo requested a review from a team September 28, 2017 11:18
@jdhealy
Copy link
Member

jdhealy commented Sep 29, 2017

Two areas of thought on this:

  1. Apple’s guidance from Hashable’s documentation:

    Important
    Hash values are not guaranteed to be equal across different executions of your program. Do not save hash values to use in a future execution.
    Maybe our use of it (likewise with Swift Package Manager’s) is exceptional in regards to this, @ikesyo? Pulling in a hashing library might give us more dependable behavior, at the expense of having to write code for each property (so, some overhead).

  2. Case-sensitivity (filesystems, GitHub request URLs, GitHub response URLs): what we are currently relying on, what this PR would rely on, what we can realistically support — something (given some free time) I hope to reexamine cross-project. Eventually and ideally, we would have documentation above Dependency regarding case-sensitivity.

Edit: grammar.

@jdhealy jdhealy self-assigned this Sep 29, 2017
@ikesyo ikesyo changed the title Avoid name collision on fetching with appending the hash value of a dependency [WIP] Avoid name collision on fetching with appending the hash value of a dependency Oct 5, 2017
@ikesyo
Copy link
Member Author

ikesyo commented Oct 21, 2017

Maybe our use of it (likewise with Swift Package Manager’s) is exceptional in regards to this, @ikesyo? Pulling in a hashing library might give us more dependable behavior, at the expense of having to write code for each property (so, some overhead).

@jdhealy How does this look like?

dcefa9a

@ikesyo ikesyo changed the title [WIP] Avoid name collision on fetching with appending the hash value of a dependency Avoid name collision on fetching with appending the hash value of a dependency Oct 21, 2017
Copy link
Contributor

@NachoSoto NachoSoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍

Copy link
Member

@jdhealy jdhealy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still not sure about the case-sensitivity aspects of this. 🤔

@ikesyo
Copy link
Member Author

ikesyo commented Oct 23, 2017

Case-sensitivity (filesystems, GitHub request URLs, GitHub response URLs): what we are currently relying on, what this PR would rely on, what we can realistically support — something (given some free time) I hope to reexamine cross-project. Eventually and ideally, we would have documentation above Dependency regarding case-sensitivity.

@jdhealy I'm sorry but I assume you would do the job, isn't it? Please let me know your knowledge about this atm and I may succeed that.

import Tentacle

/// Uniquely identifies a project that can be used as a dependency.
public enum Dependency {
/// A repository hosted on GitHub.com or GitHub Enterprise.
/// This is treated as case-insensitive.
case gitHub(Server, Repository)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case gitHub(Server, Repository)

/// An arbitrary Git repository.
/// This is treated as case-sensitive.
case git(GitURL)
Copy link
Member Author

@ikesyo ikesyo Nov 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitURL's equality is based on normalizedURLString and there is no case-insensitive comparisons or case conversions in that implementation.

  • /// A normalized URL string, without protocol, authentication, or port
    /// information. This is mostly useful for comparison, and not for any
    /// actual Git operations.
    internal var normalizedURLString: String {
    if let parsedURL = URL(string: urlString), let host = parsedURL.host {
    // Normal, valid URL.
    let path = strippingGitSuffix(parsedURL.path)
    return "\(host)\(path)"
    } else if urlString.hasPrefix("/") // "/path/to/..."
    || urlString.hasPrefix(".") // "./path/to/...", "../path/to/..."
    || urlString.hasPrefix("~") // "~/path/to/..."
    || !urlString.contains(":") // "path/to/..." with avoiding "git@github.com:owner/name"
    {
    // Local path.
    return strippingGitSuffix(urlString)
    } else {
    // scp syntax.
    var strippedURLString = urlString
    if let index = strippedURLString.index(of: "@") {
    strippedURLString.removeSubrange(strippedURLString.startIndex...index)
    }
    var host = ""
    if let index = strippedURLString.index(of: ":") {
    host = String(strippedURLString[strippedURLString.startIndex..<index])
    strippedURLString.removeSubrange(strippedURLString.startIndex...index)
    }
    var path = strippingGitSuffix(strippedURLString)
    if !path.hasPrefix("/") {
    // This probably isn't strictly legit, but we'll have a forward
    // slash for other URL types.
    path.insert("/", at: path.startIndex)
    }
    return "\(host)\(path)"
    }
    }
  • public static func == (_ lhs: GitURL, _ rhs: GitURL) -> Bool {
    return lhs.normalizedURLString == rhs.normalizedURLString
    }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case git(GitURL)

/// A binary-only framework
/// This is treated as case-sensitive.
case binary(URL)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import Foundation

URL(string: "https://google.com") == URL(string: "https://google.COM") // false

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdiep
Copy link
Member

mdiep commented Nov 14, 2017

This would definitely fix the issue, but I don't think it's the best approach from an end-user perspective. Switching to a fork would require a full clone of the repository.

I think a better solution would be to always use the same repository for a given name, but to use a different git remote for each possible origin. For GitHub.com repositories, the name of the remote could just be the name of the owner. For other repositories, we could do essentially what you've done here.

The origin approach would share the git object database across all forks, leading to faster clones and saved disk space. It would also preserve everyones' caches when they upgrade to get this PR.

What do you think @ikesyo? Does that seem workable? If so, what would you think of pursuing that instead?

@@ -27,6 +32,23 @@ public enum Dependency {
}
}

/// The unique identifier for this project which is useful as a file system path.
public var fileSystemIdentifier: SignalProducer<String, CarthageError> {
let task = Task("/usr/bin/shasum", arguments: ["-a", "256"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate shelling out for things like this. But I guess there's probably not an easy Swift option. 😞

@ikesyo
Copy link
Member Author

ikesyo commented Nov 14, 2017

Hmm so let’s revert #2125 for now.

@ikesyo
Copy link
Member Author

ikesyo commented Dec 25, 2017

Reopened and rebased on current master.

@mdiep
Copy link
Member

mdiep commented Jan 2, 2018

@ikesyo What do you think of the idea I described in #2286 (comment)?

I think that the best solution here is to move the cache to ~/Library/Caches/org.carthage.CarthageKit/repositories/{ProjectName}/{OwnerOrURL}. That cleans things up quite a bit and makes the cache more navigable and debuggable.

I haven't found Xcode's derived data folder, with hash-appended directories, to be very user-friendly. And although I'm sure the Xcode team would say that you don't need to navigate there, I've found that I often do need too. In other words, there's prior-art for using the hash-appended directory name, but I don't think it's particularly good art.

@stale
Copy link

stale bot commented Jun 30, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jun 30, 2018
@ikesyo
Copy link
Member Author

ikesyo commented Jul 4, 2018

#2185 (comment)

I'd like to revisit that direction.

@stale stale bot removed the stale label Jul 4, 2018
@ikesyo ikesyo closed this Jun 14, 2021
@ikesyo ikesyo deleted the avoid-repo-name-collision branch June 14, 2021 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cache failing to resolve dependencies with name collision Version 0.25.0 downgrades frameworks
4 participants