Skip to content

Commit

Permalink
handle quoted strings from git porcelain
Browse files Browse the repository at this point in the history
This seems to be another reason to switch over to Z mode, but for now
this matches the behavior of scm_breeze.
  • Loading branch information
mroth committed Mar 4, 2015
1 parent 9857939 commit a4f2282
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 3 deletions.
15 changes: 12 additions & 3 deletions commands/status/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,23 @@ ProcessFile extracts the filename from a status change, and determines the
absolute and relative paths.
Parameters:
- c: the raw bytes representing a status change
- c: the raw bytes representing a status change from `git status --porcelain`
- root: the absolute path to the git working tree
*/
func extractFile(chunk []byte, root, wd string) (absPath, relPath string) {
// file identifier starts at pos4 and continues to EOL
file := string(chunk[3:len(chunk)])
absPath = filepath.Join(root, file)

relPath, err := filepath.Rel(wd, absPath)
// try to unquote it, for instances where git --porcelain quotes for special
// characters
unquoted, err := strconv.Unquote(file)
if err == nil {
file = unquoted
}

// determine absolute and relative paths
absPath = filepath.Join(root, file)
relPath, err = filepath.Rel(wd, absPath)
if err != nil {
relPath = absPath
}
Expand Down
33 changes: 33 additions & 0 deletions commands/status/process_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,39 @@ var testCasesExtractFile = []struct {
expectedAbs: "/tmp/foo/bar/narwhal/disco/yyy",
expectedRel: "../../narwhal/disco/yyy",
},
{
root: "/tmp/foo",
wd: "/tmp/foo",
chunk: []byte("R foo.txt -> bar.txt"),
expectedAbs: "/tmp/foo/foo.txt -> bar.txt", // same as scmbreeze, but problematic?
expectedRel: "foo.txt -> bar.txt", // same as scmbreeze, but problematic?
},
// following examples are ones where scm_breeze strips the escaping that
// git status --porcelain does in certain cases. Using -z would have probably
// been a better way to go, but for now lets see if we can replicate it...
// (note: scm_breeze fails on complex cases of this, we dont use it as source
// of truth for correctness!)
{
root: "/tmp/foo",
wd: "/tmp/foo",
chunk: []byte(`A "hi there mom.txt"`),
expectedAbs: "/tmp/foo/hi there mom.txt",
expectedRel: "hi there mom.txt",
},
{
root: "/tmp/foo",
wd: "/tmp/foo/bar",
chunk: []byte(`?? "\"x.txt"`),
expectedAbs: `/tmp/foo/"x.txt`,
expectedRel: `../"x.txt`,
},
{
root: "/tmp/foo",
wd: "/tmp/foo",
chunk: []byte(`?? "hi m\"o\"m.txt"`),
expectedAbs: `/tmp/foo/hi m"o"m.txt`, //scmbreeze fails these with `hi m"o\`
expectedRel: `hi m"o"m.txt`,
},
}

func TestExtractFile(t *testing.T) {
Expand Down
41 changes: 41 additions & 0 deletions features/shell_wrappers.feature
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,44 @@ Feature: optional wrapping of normal git cmds in the shell
| shell |
| bash |
| zsh |


Scenario Outline: Wrapped `git add` can handle files with spaces properly
Given I am in a git repository
And an empty file named "file with spaces.txt"
When I run `<shell>` interactively
And I type `eval "$(scmpuff init -ws)"`
And I type "scmpuff_status"
And I type "git add 1"
And I type "exit"
Then the exit status should be 0
And the output should match /new file:\s+\[1\] file with spaces.txt/
Examples:
| shell |
| bash |
| zsh |


Scenario Outline: Wrapped `git reset` can handle files with spaces properly
This is different and more complex because `git status --porcelain` puts it
inside quotes for the case where it is already added (but doesnt in the ??
case surprisingly), and also it expands using --relative.

Given I am in a git repository
And an empty file named "file with spaces.txt"
And I successfully run `git add "file with spaces.txt"`
When I run `<shell>` interactively
And I type `eval "$(scmpuff init -ws)"`
And I type "scmpuff_status"
And I type "git reset 1"
And I type "exit"
Then the exit status should be 0
When I run `scmpuff status`
Then the stdout from "scmpuff status" should contain:
"""
untracked: [1] file with spaces.txt
"""
Examples:
| shell |
| bash |
| zsh |

0 comments on commit a4f2282

Please sign in to comment.