diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cbd6d14..5bc2e2a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fetch diff output uses correct remote branch (#509) - Properly handle more cases of truncated filenames from git pull (#511) - Made git-source-control backwards compatible with IRIS 2021.1 (#513) +- Sync, pull properly handle more change edge cases for import (#517, #496) ## [2.5.0] - 2024-09-24 diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls index 0239f9e6..5d628c5d 100644 --- a/cls/SourceControl/Git/Utils.cls +++ b/cls/SourceControl/Git/Utils.cls @@ -447,8 +447,7 @@ ClassMethod MergeDefaultRemoteBranch(Output alert As %String = "") As %Boolean do ..RunGitWithArgs(.errStream, .outStream, "fetch", "origin", defaultMergeBranch_":"_defaultMergeBranch) do ..PrintStreams(errStream, outStream) - do ..RunGitWithArgs(,.outStream, "rev-parse", "HEAD") - set startSha = outStream.ReadLine() + set startSha = ..GetCurrentRevision() // Start a transaction so code changes can be rolled back set initTLevel = $TLevel @@ -556,6 +555,13 @@ ClassMethod GetCurrentBranch() As %String quit branchName } +ClassMethod GetCurrentRevision() As %String +{ + do ##class(SourceControl.Git.Utils).RunGitCommandWithInput("rev-parse",,.errStream,.outStream,"HEAD") + set revision = outStream.ReadLine(outStream.Size) + quit revision +} + ClassMethod Pull(remote As %String = "origin") As %Status { New %gitSCOutputFlag @@ -1731,7 +1737,11 @@ ClassMethod RunGitCommandWithInput(command As %String, inFile As %String = "", O } elseif (command = "restore") { // Leave diffCompare empty, this actually does the right thing. set syncIrisWithDiff = 1 - } elseif (command = "merge") || (command = "rebase") || (command = "pull") { + } elseif (command = "pull") { + set syncIrisWithDiff = 1 + // The current revision, prior to the pull, will be compared against + set diffCompare = ..GetCurrentRevision() + } elseif (command = "merge") || (command = "rebase") { set syncIrisWithCommand = 1 if $data(args) && $data(args(args),diffCompare) { // no-op @@ -1795,7 +1805,10 @@ ClassMethod RunGitCommandWithInput(command As %String, inFile As %String = "", O set syncIrisWithCommand = 0 } - if syncIrisWithDiff { + // If performing a pull don't perform a diff until after the pull has occured. + // This is to avoid a double fetch, as pull performs one for us and also to avoid a potential + // race condition if the remote changes between now and the pull actually being performed. + if syncIrisWithDiff && (command '= "pull") { if diffBase = "" { set diffBase = ..GetCurrentBranch() } @@ -1809,23 +1822,30 @@ ClassMethod RunGitCommandWithInput(command As %String, inFile As %String = "", O set outLog = ##class(%Library.File).TempFilename() set errLog = ##class(%Library.File).TempFilename() - set command = $extract(..GitBinPath(),2,*-1) + set gitCommand = $extract(..GitBinPath(),2,*-1) set baseArgs = "/STDOUT="_$$$QUOTE(outLog)_" /STDERR="_$$$QUOTE(errLog)_$case(inFile, "":"", :" /STDIN="_$$$QUOTE(inFile)) try { // Inject instance manager directory as global git config home directory // On Linux, this avoids trying to use /root/.config/git/attributes for global git config set env("XDG_CONFIG_HOME") = ##class(%File).ManagerDirectory() - set returnCode = $zf(-100,"/ENV=env... "_baseArgs,command,newArgs...) + set returnCode = $zf(-100,"/ENV=env... "_baseArgs,gitCommand,newArgs...) } catch e { if $$$isWINDOWS { - set returnCode = $zf(-100,baseArgs,command,newArgs...) + set returnCode = $zf(-100,baseArgs,gitCommand,newArgs...) } else { // If can't inject XDG_CONFIG_HOME (older IRIS version), need /SHELL on Linux to avoid permissions errors trying to use root's config - set returnCode = $zf(-100,"/SHELL "_baseArgs,command,newArgs...) + set returnCode = $zf(-100,"/SHELL "_baseArgs,gitCommand,newArgs...) } } + // If performing a pull then do a diff now after the pull has occured. + if syncIrisWithDiff && (command = "pull") { + do ##class(SourceControl.Git.Utils).RunGitCommandWithInput("diff",,.errorStream,.outputStream, diffCompare, "--name-status") + // Verbose output should not be required as pull already outputs a summary + do ..ParseDiffStream(outputStream,0,.files) + } + set errStream = ##class(%Stream.FileCharacter).%OpenId(errLog,,.sc) set outStream = ##class(%Stream.FileCharacter).%OpenId(outLog,,.sc) set outStream.TranslateTable="UTF8"