Repository: remotemobprogramming/mob
Pull request #388 (2023-05-14 11:27:47)

Open last modified file with spaces in path
This is my attempt to allow opening last modified files when the project path on disk contains spaces. I also opened issue  #387 with further details.

The test I added works with a last modified file containing spaces instead of a project path containing spaces, as this was way easier to set up for me and seems to exhibit the same behavior.

As I have no prior experience with Go, I assume my code is not idiomatic. Also, I have not yet extracted functions yet. Therefore, feedback about how my code better fits into the codebase is greatly appreciated.

hollesse: Hey @kriber82 thank you for your contribution and also the well described issue :) I will have a look at it later, when i have some time. But my first impression is, that it looks good :) 
hollesse: closes #387 
kriber82: I will incorporate your feedback, when I find time, which will probably be sometime next week.
gregorriegler: Hi @kriber82 do you think you will find the time for making the improvements?
kriber82: Sorry for the huge delay. Will try to do it within the next days.

Patch:
diff --git a/mob.go b/mob.go
index 9b71ced..ceaa360 100644
--- a/mob.go
+++ b/mob.go
@@ -41,7 +41,11 @@ func openCommandFor(c config.Configuration, filepath string) (string, []string)
 	if !c.IsOpenCommandGiven() {
 		return "", []string{}
 	}
-	split := strings.Split(injectCommandWithMessage(c.OpenCommand, filepath), " ")
+	filepathWithoutSpaces := strings.ReplaceAll(filepath, " ", "&spc&")
+	split := strings.Split(injectCommandWithMessage(c.OpenCommand, filepathWithoutSpaces), " ")
+	for i := 0; i < len(split); i++ {
+		split[i] = strings.ReplaceAll(split[i], "&spc&", " ")
+	}
 	return split[0], split[1:]
 }
 
@@ -938,6 +942,9 @@ func openLastModifiedFileIfPresent(configuration config.Configuration) {
 		return
 	}
 	lastModifiedFile := split[1]
+	if strings.HasPrefix(lastModifiedFile, "\"") {
+		lastModifiedFile, _ = strconv.Unquote(lastModifiedFile)
+	}
 	if lastModifiedFile == "" {
 		say.Debug("Could not find last modified file in commit message")
 		return
@@ -1034,7 +1041,7 @@ func startNewMobSession(configuration config.Configuration) {
 
 	say.Info("starting new session from " + currentBaseBranch.remote(configuration).String())
 	git("checkout", "-B", currentWipBranch.Name, currentBaseBranch.remote(configuration).Name)
-	git("commit", "--allow-empty", "-m", configuration.StartCommitMessage)
+	git("commit", gitHooksOption(configuration), "--allow-empty", "-m", configuration.StartCommitMessage)
 	gitPush(gitHooksOption(configuration), "--set-upstream", configuration.RemoteName, currentWipBranch.Name+":"+currentWipBranch.Name)
 }
 


Test patch:
diff --git a/mob_test.go b/mob_test.go
index 259a285..f40fbfc 100644
--- a/mob_test.go
+++ b/mob_test.go
@@ -237,6 +237,16 @@ func TestStart(t *testing.T) {
 	assertMobSessionBranches(t, configuration, "mob-session")
 }
 
+func TestStartDespiteGitHook(t *testing.T) {
+	_, configuration := setup(t)
+	createExecutableFileInPath(t, workingDir+"/.git/hooks", "pre-commit", "#!/bin/sh\necho 'boo'\nexit 1\n")
+
+	start(configuration)
+
+	assertOnBranch(t, "mob-session")
+	assertMobSessionBranches(t, configuration, "mob-session")
+}
+
 func TestStartWithCISkip(t *testing.T) {
 	_, configuration := setup(t)
 
@@ -884,6 +894,27 @@ func TestStartNextStay_OpenLastModifiedFile(t *testing.T) {
 	})
 }
 
+func TestStartNextStay_OpenLastModifiedFile_WhenLastModifiedFilePathContainsSpaces(t *testing.T) {
+	_, configuration := setup(t)
+	configuration.NextStay = true
+	if runtime.GOOS == "windows" {
+		configuration.OpenCommand = "cmd.exe /C type nul > %s-1"
+	} else {
+		configuration.OpenCommand = "touch %s-1"
+	}
+
+	start(configuration)
+	createFile(t, "file with spaces.txt", "contentIrrelevant")
+	assertOnBranch(t, "mob-session")
+	next(configuration)
+
+	start(configuration)
+
+	assertGitStatus(t, GitStatus{
+		"file with spaces.txt-1": "??",
+	})
+}
+
 func TestRunOutput(t *testing.T) {
 	_, configuration := setup(t)
 
@@ -1882,8 +1913,12 @@ func gitStatus() GitStatus {
 		if len(line) == 0 {
 			continue
 		}
-		file := strings.Fields(line)
-		statusMap[file[1]] = file[0]
+		fields := strings.Fields(line)
+		file := strings.Join(fields[1:], " ")
+		if strings.HasPrefix(file, "\"") {
+			file, _ = strconv.Unquote(file)
+		}
+		statusMap[file] = fields[0]
 	}
 	return statusMap
 }
@@ -2050,6 +2085,16 @@ func createFileInPath(t *testing.T, path, filename, content string) (pathToFile
 	return
 }
 
+func createExecutableFileInPath(t *testing.T, path, filename, content string) (pathToFile string) {
+	contentAsBytes := []byte(content)
+	pathToFile = path + "/" + filename
+	err := os.WriteFile(pathToFile, contentAsBytes, 0755)
+	if err != nil {
+		failWithFailure(t, "creating file "+filename+" with content "+content, "error")
+	}
+	return
+}
+
 func createDirectory(t *testing.T, directory string) (pathToFile string) {
 	return createDirectoryInPath(t, workingDir, directory)
 }