From 74cfa00427a38c95026b4517a17bab32514156f7 Mon Sep 17 00:00:00 2001
From: Georg Seibt <seibt@fim.uni-passau.de>
Date: Fri, 28 Oct 2016 15:44:27 +0200
Subject: [PATCH] add a method for converting a path string returned by git to
 a Path object

---
 .../fim/seibt/gitwrapper/repo/GitWrapper.java | 103 ++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java
index f94cef0..d9bf376 100644
--- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java
+++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/GitWrapper.java
@@ -2,11 +2,17 @@ package de.uni_passau.fim.seibt.gitwrapper.repo;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Scanner;
 import java.util.function.Function;
@@ -218,6 +224,103 @@ public class GitWrapper extends ToolWrapper {
                                             || res.getStdOutTrimmed().startsWith(ERROR_PREFIX);
     }
 
+    /**
+     * Converts the given {@code path} {@link String} to a {@link Path} object. This method will perform unquoting if
+     * necessary. If there is an exception unquoting or converting to a path an empty optional will be returned.
+     *
+     * @param path
+     *         the {@link String} to convert to a {@link Path}
+     * @return optionally the {@link Path} corresponding to the given {@link String} returned by git
+     */
+    public Optional<Path> getPath(String path) {
+        Objects.requireNonNull(path, "The given String 'path' must not be null.");
+
+        if (path.length() >= 2 && path.charAt(0) == '"' && path.charAt(path.length() - 1) == '"') {
+
+            try {
+                path = unquote(path);
+            } catch (IllegalArgumentException e) {
+                LOG.log(Level.WARNING, "Failed to unquote the path '" + path + "'.", e);
+                return Optional.empty();
+            }
+        }
+
+        try {
+            return Optional.of(Paths.get(path));
+        } catch (InvalidPathException e) {
+            LOG.log(Level.WARNING, "Failed to construct a Path object from path '" + path + "'.", e);
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Unquotes the given {@link String}. This method assumes that the given {@link String} begins and ends with the
+     * character '"'. It will replace escape sequences \a, \b, \f, \n, \r, \t, \v, \\, and \" with their corresponding
+     * unquoted characters.
+     *
+     * @param quoted
+     *         the quoted {@link String}
+     * @return the unquoted {@link String}
+     * @throws IllegalArgumentException
+     *         if the given {@link String} does not start with a '"' character or there is an
+     *         illegal escape sequence in {@code quoted}
+     */
+    private String unquote(String quoted) {
+        StringReader rdr = new StringReader(quoted);
+        StringWriter wtr = new StringWriter(quoted.length() - 2);
+
+        int ch;
+
+        try {
+            if (rdr.read() != '"') {
+                throw new IllegalArgumentException("Quoted strings begin with the character <\">");
+            }
+
+            while ((ch = rdr.read()) != -1) {
+
+                if (ch == '"') {
+                    break;
+                } else if (ch != '\\') {
+                    wtr.write(ch);
+                    continue;
+                }
+
+                switch ((ch = rdr.read())) {
+                    case 'a':
+                        wtr.write(0x07);
+                        break;
+                    case 'b':
+                        wtr.write('\b');
+                        break;
+                    case 'f':
+                        wtr.write('\f');
+                        break;
+                    case 'n':
+                        wtr.write('\n');
+                        break;
+                    case 'r':
+                        wtr.write('\r');
+                        break;
+                    case 't':
+                        wtr.write('\t');
+                        break;
+                    case 'v':
+                        wtr.write(0x0B);
+                        break;
+                    case '\\': case '"':
+                        wtr.write(ch);
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Illegal escape character <" + (char) ch + ">.");
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("The StringReader will not be closed and as such can not throw an IOException.", e);
+        }
+
+        return wtr.toString();
+    }
+
     /**
      * Executes '&lt;git command&gt &lt;firstParameter&gt &lt;parameters&gt' and returns the exit code and the output
      * of the command. If there is an exception executing the command an empty {@link Optional} will be returned.
-- 
GitLab