diff --git a/Native/MBoxWorkspace.xcodeproj/project.pbxproj b/Native/MBoxWorkspace.xcodeproj/project.pbxproj index bb1f9a7..34082fe 100644 --- a/Native/MBoxWorkspace.xcodeproj/project.pbxproj +++ b/Native/MBoxWorkspace.xcodeproj/project.pbxproj @@ -54,6 +54,8 @@ ABBB047C248688980003BCB5 /* GitSheetPush.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABBB047B248688980003BCB5 /* GitSheetPush.swift */; }; ABBD4253237955770047D954 /* Clean.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABBD4252237955770047D954 /* Clean.swift */; }; ABC33F2922D09CFF00E72978 /* Merge.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC33F2822D09CFF00E72978 /* Merge.swift */; }; + ABDE516626CFEDB6006A8B54 /* Git+Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABDE516226CFE7E2006A8B54 /* Git+Config.swift */; }; + ABDE516726CFEDFD006A8B54 /* Git+Hooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABDE516426CFEB2C006A8B54 /* Git+Hooks.swift */; }; ABDFBAE5250659B500682483 /* MBSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABA6D5A823A8E39E000BEE16 /* MBSetting.swift */; }; ABDFBAEB25065CE600682483 /* MBSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABDFBAEA25065CE600682483 /* MBSetting.swift */; }; ABDFBAED25065E6900682483 /* MBSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABDFBAEC25065E6900682483 /* MBSession.swift */; }; @@ -156,6 +158,8 @@ ABBB047B248688980003BCB5 /* GitSheetPush.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitSheetPush.swift; sourceTree = ""; }; ABBD4252237955770047D954 /* Clean.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clean.swift; sourceTree = ""; }; ABC33F2822D09CFF00E72978 /* Merge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Merge.swift; sourceTree = ""; }; + ABDE516226CFE7E2006A8B54 /* Git+Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Git+Config.swift"; sourceTree = ""; }; + ABDE516426CFEB2C006A8B54 /* Git+Hooks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Git+Hooks.swift"; sourceTree = ""; }; ABDFBAEA25065CE600682483 /* MBSetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MBSetting.swift; sourceTree = ""; }; ABDFBAEC25065E6900682483 /* MBSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MBSession.swift; sourceTree = ""; }; ABE0812224FFB13300CC8E4B /* MBoxWorkspaceLoader.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MBoxWorkspaceLoader.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -244,6 +248,7 @@ AB64A16C22A6C37400FD06FC /* CLI */ = { isa = PBXGroup; children = ( + ABDE516126CFE7A7006A8B54 /* Git */, AB36B1F42563E62A00DC9DBA /* Plugin */, AB5E306A22EC92DE004F716F /* Repo */, AB4A310822B73835005F445B /* Feature */, @@ -252,7 +257,6 @@ AB64A17522A9288C00FD06FC /* MBCommander+Workspace.swift */, AB64A18B22B12EE500FD06FC /* Add.swift */, AB4A310922B73848005F445B /* Feature.swift */, - AB64A18922B108D000FD06FC /* Git.swift */, AB4A312122BA4D52005F445B /* Remove.swift */, ABC33F2822D09CFF00E72978 /* Merge.swift */, AB64A16D22A6C3A100FD06FC /* Status.swift */, @@ -284,6 +288,16 @@ path = GitSheet; sourceTree = ""; }; + ABDE516126CFE7A7006A8B54 /* Git */ = { + isa = PBXGroup; + children = ( + AB64A18922B108D000FD06FC /* Git.swift */, + ABDE516226CFE7E2006A8B54 /* Git+Config.swift */, + ABDE516426CFEB2C006A8B54 /* Git+Hooks.swift */, + ); + path = Git; + sourceTree = ""; + }; ABE0812424FFB17E00CC8E4B /* MBoxWorkspaceLoader */ = { isa = PBXGroup; children = ( @@ -661,6 +675,7 @@ AB34F17422BF6C2300F9B86B /* import.swift in Sources */, ABBB047C248688980003BCB5 /* GitSheetPush.swift in Sources */, AB4A312022BA3FBB005F445B /* Free.swift in Sources */, + ABDE516626CFEDB6006A8B54 /* Git+Config.swift in Sources */, AB4F9EB225EBCC9000AC4D14 /* Status+Feature.swift in Sources */, AB315CEC23390E6800A73EF6 /* Env.swift in Sources */, ABEE491325C3F72300A375E8 /* MBFeature+SupportFiles.swift in Sources */, @@ -679,6 +694,7 @@ AB4A310C22B738C5005F445B /* Start.swift in Sources */, AB93AB8723B8E83C008DCBC7 /* Config.swift in Sources */, AB07110A25E64873007294A5 /* Status+Git.swift in Sources */, + ABDE516726CFEDFD006A8B54 /* Git+Hooks.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Native/MBoxWorkspace/CLI/Git/Git+Config.swift b/Native/MBoxWorkspace/CLI/Git/Git+Config.swift new file mode 100644 index 0000000..aecaf62 --- /dev/null +++ b/Native/MBoxWorkspace/CLI/Git/Git+Config.swift @@ -0,0 +1,60 @@ +// +// Git+Config.swift +// MBoxWorkspace +// +// Created by 詹迟晶 on 2021/8/20. +// Copyright © 2021 bytedance. All rights reserved. +// + +import Foundation +import MBoxCore +import MBoxGit +import MBoxWorkspaceCore + +extension MBCommander.Git { + @objc(MBCommanderGitConfig) + open class Config: Git { + open override class var flags: [Flag] { + var flags = super.flags + flags << Flag("workspace", description: "use the workspace config file") + return flags + } + + open override func setup() throws { + if self.shiftFlag("workspace") { + self.level = Self.WorkspaceLevel + } + try super.setup() + } + + open var level: String? + public static let WorkspaceLevel = "Workspace" + + open override var cmd: MBCMD { + let cmd = super.cmd as! GitCMD + cmd.pager = false + return cmd + } + + open override var args: [String] { + var args = super.args + args.insert(contentsOf: ["config"], at: 0) + if self.level == Self.WorkspaceLevel { + args.insert(contentsOf: ["-f", self.workspace.gitConfigPath], at: 1) + } + return args + } + + open override var onlyRunInWorkspace: Bool { + if self.level == Self.WorkspaceLevel { + return true + } + for flag in ["global", "system"] { + if (try? Flag(flag).parse(self.argv, shift: false)) == true { + return true + } + } + return super.onlyRunInWorkspace + } + } +} diff --git a/Native/MBoxWorkspace/CLI/Git/Git+Hooks.swift b/Native/MBoxWorkspace/CLI/Git/Git+Hooks.swift new file mode 100644 index 0000000..756a912 --- /dev/null +++ b/Native/MBoxWorkspace/CLI/Git/Git+Hooks.swift @@ -0,0 +1,54 @@ +// +// Git+Hooks.swift +// MBoxWorkspace +// +// Created by 詹迟晶 on 2021/8/20. +// Copyright © 2021 bytedance. All rights reserved. +// + +import Foundation +import MBoxCore +import MBoxGit +import MBoxWorkspaceCore + +extension MBCommander.Git { + open class Hooks: MBCommander { + open override class var description: String? { + return "Show/Set the git hooks for workspace" + } + + open override class var flags: [Flag] { + var flags = super.flags + flags << Flag("enable", description: "Enable workspace hooks") + flags << Flag("disable", description: "Enable workspace hooks") + return flags + } + + open override func setup() throws { + if self.shiftFlag("disable") { + self.enable = false + } + if self.shiftFlag("enable") { + self.enable = true + } + try super.setup() + } + + open var enable: Bool? + + open override func run() throws { + try super.run() + if let enable = self.enable { + try UI.with(verbose: true) { + try self.workspace.setupGitHooks(enable: enable) + } + } else { + if let path = try self.workspace.gitHooks() { + UI.log(info: "Workspace Git Config File: \(self.workspace.gitConfigPath)\n Workspace Hooks Directory: \(path)") + } else { + UI.log(info: "No Workspace Hooks.") + } + } + } + } +} diff --git a/Native/MBoxWorkspace/CLI/Git/Git.swift b/Native/MBoxWorkspace/CLI/Git/Git.swift new file mode 100644 index 0000000..ccdc069 --- /dev/null +++ b/Native/MBoxWorkspace/CLI/Git/Git.swift @@ -0,0 +1,55 @@ +// +// Git.swift +// MBoxWorkspace +// +// Created by Whirlwind on 2019/6/12. +// Copyright © 2019 bytedance. All rights reserved. +// + +import Foundation +import MBoxCore +import MBoxGit +import MBoxWorkspaceCore + +extension MBCommander { + open class Git: Exec { + open class override var description: String? { + return "Execute git command for every repo" + } + + open class override var arguments: [Argument] { + return [Argument("command", description: "The command will be executed", required: true)] + } + + open override var cmd: MBCMD { + let cmd = GitCMD() + cmd.showOutput = true + cmd.workingDirectory = UI.workspace?.rootPath + return cmd + } + + open class override var onlyRunInWorkspace: Bool { + return false + } + + open override var onlyRunInWorkspace: Bool { + if self.argv.remainder.count == 0 { + return true + } + return super.onlyRunInWorkspace + } + + open override func runInRepo(repo: MBWorkRepo, cmd: MBCMD, args: String) -> Int32 { + UI.with(verbose: false) { + if let git = repo.git, let branch = git.currentBranch { + if git.trackBranch(autoMatch: false) == nil, let remoteBranch = git.remoteBranch(named: branch) { + if git.setTrackBranch(local: branch, remote: remoteBranch.name) { + UI.log(info: "Set the current track branch to `\(remoteBranch.name)`.", pip: .ERR) + } + } + } + } + return super.runInRepo(repo: repo, cmd: cmd, args: args) + } + } +} diff --git a/Native/MBoxWorkspace/MBoxWorkspace.swift b/Native/MBoxWorkspace/MBoxWorkspace.swift index 30ac0a0..4af8e8a 100644 --- a/Native/MBoxWorkspace/MBoxWorkspace.swift +++ b/Native/MBoxWorkspace/MBoxWorkspace.swift @@ -42,6 +42,8 @@ open class MBoxWorkspace: NSObject, MBWorkspacePluginProtocol { MBCommanderGroup.shared.addCommand(MBCommander.Feature.Clean.self) MBCommanderGroup.shared.addCommand(MBCommander.Exec.self) MBCommanderGroup.shared.addCommand(MBCommander.Git.self) + MBCommanderGroup.shared.addCommand(MBCommander.Git.Config.self) + MBCommanderGroup.shared.addCommand(MBCommander.Git.Hooks.self) MBCommanderGroup.shared.addCommand(MBCommander.Repo.self) MBCommanderGroup.shared.addCommand(MBCommander.Repo.Search.self) MBCommanderGroup.shared.addCommand(MBCommander.GitSheet.self) diff --git a/Native/MBoxWorkspaceCore/Model/MBWorkspace.swift b/Native/MBoxWorkspaceCore/Model/MBWorkspace.swift index 0e13f7a..528ed78 100644 --- a/Native/MBoxWorkspaceCore/Model/MBWorkspace.swift +++ b/Native/MBoxWorkspaceCore/Model/MBWorkspace.swift @@ -347,15 +347,41 @@ open class MBWorkspace: NSObject { // MARK: - Git open lazy var gitConfigPath: String = self.configDir.appending(pathComponent: "git.config") + open func gitConfig(for key: String) throws -> String? { + return try UI.log(verbose: "Get git workspace config: \(key):") { + return try GitHelper.getConfig(for: key, path: self.gitConfigPath) + } + } + open func setGitConfig(_ value: String, for key: String) throws { - try GitHelper.setConfig(key: key, value: value, path: self.gitConfigPath) + try UI.log(verbose: "Set git workspace config: \(key): \(value)") { + try GitHelper.setConfig(key: key, value: value, path: self.gitConfigPath) + } + } + + open func removeGitConfig(for key: String) throws { + try UI.log(verbose: "Remove git workspace config: \(key)") { + try GitHelper.removeConfig(key: key, path: self.gitConfigPath) + } } dynamic open func setupGitConfig() throws { try self.setGitConfig("current", for: "push.default") - if let hookPath = MBWorkspace.pluginPackage?.resoucePath(for: "gitHookManager") { - try self.setGitConfig(hookPath, for: "core.hooksPath") + try self.setupGitHooks(enable: true) + } + + open func gitHooks() throws -> String? { + return try self.gitConfig(for: "core.hooksPath") + } + + open func setupGitHooks(enable: Bool) throws { + if enable { + if let hookPath = MBWorkspace.pluginPackage?.resoucePath(for: "gitHookManager") { + try self.setGitConfig(hookPath, for: "core.hooksPath") + } + } else { + try self.removeGitConfig(for: "core.hooksPath") } }