Skip to content

Support tracking dependencies by branch #16

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# By default export all variables
export

.PHONY: install release debug build setup clean
.PHONY: install release debug build setup clean test

PROJECT ?= 'modulo.xcodeproj'
SCHEME ?= 'modulo'
Expand All @@ -11,6 +11,9 @@ CONFIGURATION ?= 'Debug'
# Build for debugging
debug: build

test:
xcodebuild -project $(PROJECT) -scheme ModuloKit test

# Install `modulo` to `/usr/local/bin`
install: release
cp $(SYMROOT)/Release/modulo /usr/local/bin/
Expand Down
15 changes: 14 additions & 1 deletion Modules/ELCLI/ELCLI/CLI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,20 @@ open class CLI {
// it's a "--flag value" type argument.
if index < arguments.count - 1 {
value = arguments[index + 1]
skipNext = true
// If we're assuming `--flag value` make sure
// our `value` isn't a stop marker or flag. If it is
// our value should instead be `nil`'d out so our
// command does not get a value where it is our next
// argument.
if let argValue = value,
isStopMarker(argValue) || isFlag(argValue) {
value = nil
} else {
// However if that's not the case we should skip
// the next command because we really did get
// `--flag value`
skipNext = true
}
}
}
}
Expand Down
23 changes: 19 additions & 4 deletions ModuloKit/Actions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ open class Actions {
}
}

open func addDependency(_ url: String, version: SemverRange?, unmanaged: Bool) -> ErrorCode {
let dep = DependencySpec(repositoryURL: url, version: version)
open func addDependency(_ url: String, version: SemverRange?, unmanagedValue: String?, unmanaged: Bool) -> ErrorCode {
let dep = DependencySpec(repositoryURL: url, version: version, unmanagedValue: unmanagedValue)
if var workingSpec = ModuleSpec.workingSpec() {
// does this dep already exist in here??
if let _ = workingSpec.dependencyForURL(url) {
Expand Down Expand Up @@ -77,6 +77,16 @@ open class Actions {
exit(checkoutResult.errorMessage())
}
}
if let unmanagedValue = dep.unmanagedValue {
let checkoutResult = scm.checkout(branchOrHash: unmanagedValue, path: clonePath)
if checkoutResult != .success {
exit(checkoutResult.errorMessage())
}
let pullResult = scm.pull(clonePath, remoteData: nil)
if pullResult != .success {
exit(pullResult.errorMessage())
}
}

// things worked, so add it to the approprate place in the overall state.
if explicit {
Expand All @@ -92,7 +102,7 @@ open class Actions {
}

// if they're unmanaged and on a branch, tracking a remote, just do a pull
if dep.unmanaged == true, let currentBranch = scm.branchName(clonePath) {
if dep.unmanaged == true && dep.unmanagedValue == nil, let currentBranch = scm.branchName(clonePath) {
if scm.remoteTrackingBranch(currentBranch) != nil {
let pullResult = scm.pull(clonePath, remoteData: nil)
if pullResult != .success {
Expand All @@ -106,8 +116,13 @@ open class Actions {
if checkoutResult != .success {
exit(checkoutResult.errorMessage())
}
} else if let unmanagedValue = dep.unmanagedValue {
let checkoutResult = scm.checkout(branchOrHash: unmanagedValue, path: clonePath)
if checkoutResult != .success {
exit(checkoutResult.errorMessage())
}
} else {
exit("\(dep.name()) doesn't have a version and isn't unmanaged, not sure what to do.")
exit("\(dep.name()) doesn't have a version and isn't marked as 'unmanaged', not sure what to do.")
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions ModuloKit/Commands/AddCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ open class AddCommand: NSObject, Command {
fileprivate var repositoryURL: String! = nil
fileprivate var shouldUpdate: Bool = false
fileprivate var unmanaged: Bool = false
fileprivate var unmanagedValue: String? = nil

// Protocol conformance
open var name: String { return "add" }
Expand All @@ -41,8 +42,9 @@ open class AddCommand: NSObject, Command {
}
}

addOption(["--unmanaged"], usage: "specifies that this module will be unmanaged") { (option, value) in
addOptionValue(["--unmanaged"], usage: "specifies that this module will be unmanaged", valueSignature: "<[hash|branch|nothing]>") { (option, value) -> Void in
self.unmanaged = true
self.unmanagedValue = value
}

addOption(["-u", "--update"], usage: "performs the update command after adding a module") { (option, value) in
Expand All @@ -58,7 +60,7 @@ open class AddCommand: NSObject, Command {
let actions = Actions()

if version == nil && unmanaged == false {
writeln(.stderr, "A version or range must be specified via --version, or --unmanaged must be used.")
writeln(.stderr, "A version or range must be specified via --version or --unmanaged must be used.")
return ErrorCode.commandError.rawValue
}

Expand All @@ -69,7 +71,7 @@ open class AddCommand: NSObject, Command {
}
}

let result = actions.addDependency(repositoryURL, version: version, unmanaged: unmanaged)
let result = actions.addDependency(repositoryURL, version: version, unmanagedValue: unmanagedValue, unmanaged: unmanaged)
if result == .success {
if shouldUpdate {
writeln(.stdout, "Added \(String(describing: repositoryURL)).")
Expand Down
45 changes: 44 additions & 1 deletion ModuloKit/SCM/Git.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ open class Git: SCM {
let initialWorkingPath = FileManager.workingPath()
FileManager.setWorkingPath(path)

let updateCommand = "git fetch --recurse-submodules --all --tags"
let updateCommand = "git fetch --recurse-submodules --all"
let status = runCommand(updateCommand)

FileManager.setWorkingPath(initialWorkingPath)
Expand Down Expand Up @@ -175,6 +175,49 @@ open class Git: SCM {

return .success
}

open func checkout(branchOrHash: String, path: String) -> SCMResult {
if !FileManager.fileExists(path) {
return .error(code: 1, message: "Module path '\(path)' does not exist.")
}

var checkoutCommand = ""

let initialWorkingPath = FileManager.workingPath()
FileManager.setWorkingPath(path)

// try fetching it directly
let fetchResult = runCommand("git fetch origin \(branchOrHash)")

if branches(".").contains(branchOrHash) {
checkoutCommand = "git checkout origin/\(branchOrHash) --quiet"
} else {
checkoutCommand = "git checkout \(branchOrHash) --quiet"
}

if fetchResult != 0 {
if verbose {
writeln(.stderr, "Unable to find unmanaged value '\(branchOrHash)'.")
}
return .error(code: SCMDefaultError, message: "Unable to find a match for \(branchOrHash).")
}

let status = runCommand(checkoutCommand)

let submodulesResult = collectAnySubmodules()

FileManager.setWorkingPath(initialWorkingPath)

if status != 0 {
return .error(code: status, message: "Unable to checkout '\(branchOrHash)'.")
}

if submodulesResult != .success {
return submodulesResult
}

return .success
}

open func adjustIgnoreFile(pattern: String, removing: Bool) -> SCMResult {
let localModulesPath = State.instance.modulePathName
Expand Down
3 changes: 3 additions & 0 deletions ModuloKit/SCM/SCM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ public protocol SCM {
func fetch(_ path: String) -> SCMResult
func pull(_ path: String, remoteData: String?) -> SCMResult
func checkout(version: SemverRange, path: String) -> SCMResult
/// Check out an arbitrary point or the HEAD of a branch (in git)
/// or the equivalent in other SCM solutions
func checkout(branchOrHash: String, path: String) -> SCMResult
func remove(_ path: String) -> SCMResult
func adjustIgnoreFile(pattern: String, removing: Bool) -> SCMResult
func checkStatus(_ path: String) -> SCMResult
Expand Down
9 changes: 7 additions & 2 deletions ModuloKit/Specs/DependencySpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public struct DependencySpec {
var repositoryURL: String
// version or version range
var version: SemverRange?
/// Optional unmanaged property to track
/// such as a branch name, commit hash, or nothing
var unmanagedValue: String?
Copy link

@cgarvin647 cgarvin647 Oct 1, 2018

Choose a reason for hiding this comment

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

Is unmanagedValue the right name for this? Maybe we could use unmanagedBranchOrHash, unmanagedCheckout. Honestly I'm not so sure I agree with the --unmanaged name option. It isn't unmanaging anything, it's more not using a version. unversioned?


var unmanaged: Bool {
get {
Expand All @@ -29,7 +32,8 @@ extension DependencySpec: ELDecodable {
public static func decode(_ json: JSON?) throws -> DependencySpec {
return try DependencySpec(
repositoryURL: json ==> "repositoryURL",
version: json ==> "version"
version: json ==> "version",
unmanagedValue: json ==> "unmanagedValue"
)
}

Expand All @@ -42,7 +46,8 @@ extension DependencySpec: ELEncodable {
public func encode() throws -> JSON {
return try encodeToJSON([
"repositoryURL" <== repositoryURL,
"version" <== version
"version" <== version,
"unmanagedValue" <== unmanagedValue
])
}
}
Expand Down
57 changes: 57 additions & 0 deletions ModuloKitTests/TestAdd.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,61 @@ class TestAdd: XCTestCase {

FileManager.setWorkingPath("..")
}

func testAddUnmanagedModuleWithBranch() {
let status = Git().clone("[email protected]:modulo-dm/test-add.git", path: "test-add")
XCTAssertTrue(status == .success)

FileManager.setWorkingPath("test-add")

let repoURL = "[email protected]:modulo-dm/test-add-update.git"

let result = Modulo.run(["add", repoURL, "--unmanaged", "master", "-v"])
XCTAssertTrue(result == .success)


guard let spec = ModuleSpec.load(contentsOfFile: specFilename) else {
XCTFail("Failed to get spec from file \(specFilename)")
return }
XCTAssertTrue(spec.dependencies.count > 0)
guard let dep = spec.dependencyForURL(repoURL) else {
XCTFail("Failed to find dependency for url \(repoURL) in spec \(spec)")
return }
XCTAssertNil(dep.version)
XCTAssertTrue(dep.unmanaged)
XCTAssertNotNil(dep.unmanagedValue)
XCTAssertTrue(dep.unmanagedValue == "master")

FileManager.setWorkingPath("..")

Git().remove("test-add")
}

func testAddModuleUnmanagedNoArgs() {
let status = Git().clone("[email protected]:modulo-dm/test-add.git", path: "test-add")
XCTAssertTrue(status == .success)

FileManager.setWorkingPath("test-add")

let repoURL = "[email protected]:modulo-dm/test-add-update.git"

let result = Modulo.run(["add", repoURL, "--unmanaged", "-v"])
XCTAssertTrue(result == .success)


guard let spec = ModuleSpec.load(contentsOfFile: specFilename) else {
XCTFail("Failed to get spec from file \(specFilename)")
return }
XCTAssertTrue(spec.dependencies.count > 0)
guard let dep = spec.dependencyForURL(repoURL) else {
XCTFail("Failed to find dependency for url \(repoURL) in spec \(spec)")
return }
XCTAssertNil(dep.version)
XCTAssertTrue(dep.unmanaged)
XCTAssertNil(dep.unmanagedValue)

FileManager.setWorkingPath("..")

Git().remove("test-add")
}
}
2 changes: 1 addition & 1 deletion ModuloKitTests/TestDummyApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class TestDummyApp: XCTestCase {
XCTAssertTrue(spec!.dependencyForURL("[email protected]:modulo-dm/test-add-update.git") != nil)

let checkedOut = Git().branchName("modules/test-add-update")
XCTAssertTrue(checkedOut == "master")
XCTAssertTrue(checkedOut == "master", "checkedOut should have been 'master' but was '\(String(describing: checkedOut))'")

XCTAssertTrue(FileManager.fileExists("modules/test-add-update"))
XCTAssertTrue(FileManager.fileExists("modules/test-dep1"))
Expand Down
4 changes: 2 additions & 2 deletions modulo.xcodeproj/xcshareddata/xcschemes/modulo.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@
</CommandLineArgument>
<CommandLineArgument
argument = "defaults --set --alwaysVerbose true"
isEnabled = "YES">
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "update --verbose"
isEnabled = "NO">
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "update"
Expand Down