Supports for the git command using jgit-cli.
It runs the git command for the selected resource.
Change-Id: Ib63b061d234fd2d989d574a5fa08ebfb41671f80
Signed-off-by: kh5325.kim <kh5325.kim@samsung.com>
<classpathentry kind="lib" path="lib/jsoup-1.6.3.jar"/>\r
<classpathentry kind="lib" path="lib/howdoi.jar"/>\r
<classpathentry kind="lib" path="lib/commons-math3-3.2.jar"/>\r
+ <classpathentry kind="lib" path="lib/jgit-cli.jar"/>\r
<classpathentry kind="output" path="bin"/>\r
</classpath>\r
org.tizen.common
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.eclipse.core.resources,
+ org.eclipse.jdt.core,
org.eclipse.jface.text,
org.eclipse.ui.console,
org.eclipse.ui.dialogs,
lib/httpclient-4.2.5.jar,
lib/httpcore-4.2.4.jar,
lib/commons-math3-3.2.jar,
+ lib/jgit-cli.jar,
.
about_files/,\
schema/,\
lib/commons-math3-3.2.jar,\
- resources/
+ resources/,\
+ lib/jgit-cli.jar
public class CommandProvider extends TextAssistContentProvider implements OrderProcessor {\r
Pattern PROJECT_COMMAND_PATTERN = Pattern.compile("(@[\\w]+)(\\s.*)*");\r
Pattern SDB_COMMAND_PATTERN = Pattern.compile("(" + Commands.SDB_COMMAND + ")(\\s.*)*");\r
+ Pattern GIT_COMMAND_PATTERN = Pattern.compile("(" + Commands.GIT_COMMAND + ")(\\s.*)*");\r
\r
private int numberOfMostCommons = 3;\r
private int numberOfHistory = 5;\r
void onProject();\r
void onProjectCommand(String projectName, String arg);\r
void onSdbCommand(String sdbCommand, String arg);\r
+ void onGitCommand(String gitCommand, String arg);\r
void onDefault(String arg);\r
}\r
\r
callback.onSdbCommand(sdbCommand, arg);\r
}\r
}\r
+ else if (key.startsWith(Commands.GIT_COMMAND)) {\r
+ Matcher m = GIT_COMMAND_PATTERN.matcher(key);\r
+ if (m.find()) {\r
+ String gitCommand = m.group(1);\r
+ String arg = m.group(2);\r
+ callback.onGitCommand(gitCommand, arg);\r
+ }\r
+ }\r
else {\r
callback.onDefault(key);\r
}\r
}\r
\r
@Override\r
+ public void onGitCommand(String gitCommand, String arg) {\r
+ for (String[] cmds : Commands.GIT_COMMANDS) {\r
+ returnedList.add(new String[] { gitCommand + " " + cmds[0], cmds[1] });\r
+ }\r
+ }\r
+\r
+ @Override\r
public void onDefault(String arg) {\r
returnedList.addAll(getHelpContent(arg));\r
}\r
public final static String IDENTIFIER_SYSTEM_COMMAND = "#";\r
public final static String HELP_COMMAND = "help";\r
public final static String PROJECT_COMMAND = "@";\r
+ public final static String GIT_COMMAND = "git";\r
+ public final static String[][] GIT_COMMANDS = {\r
+ { "add", "Add file contents to the index" },\r
+ { "branch", "List, create, or delete branches" },\r
+ { "checkout", "Checkout a branch to the working tree" },\r
+ { "clone", "Clone a repository into a new directory" },\r
+ { "commit", "Record changes to the repository" },\r
+ { "diff", "Show diffs" },\r
+ { "fetch", "Update remote refs from another repository" },\r
+ { "init", "Create an empty git repository" },\r
+ { "log", "View commit history" },\r
+ { "merge", "Merges two development histories" },\r
+ { "push", "Update remote repository from local refs" },\r
+ { "reset", "Reset current HEAD to the specified state" },\r
+ { "rm", "Remove files from the working tree and from the index" },\r
+ { "show", "Display one commit" },\r
+ { "status", "Show the working tree status" },\r
+ { "tag", "Create a tag" }\r
+ };\r
public final static String QUERY_COMMAND = "query";\r
public final static String SDB_COMMAND = "sdb";\r
public final static String[] SDB_COMMANDS = {\r
}\r
\r
@Override\r
+ public void onGitCommand(String gitCommand, String arg) {\r
+ }\r
+\r
+ @Override\r
public void onDefault(String arg) {\r
}\r
\r
--- /dev/null
+/*
+ * Common
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Changhyun Lee <changhyun1.lee@samsung.com>
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>
+ * BonYong Lee <bonyong.lee@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+package org.tizen.common.ui.commandbar.command;
+
+import static org.tizen.common.ui.commandbar.command.git.Command.CONTEXT_CONSOLE;
+import static org.tizen.common.ui.commandbar.command.git.Command.CONTEXT_RESOURCE_PATH;
+
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.tizen.common.core.command.Command;
+import org.tizen.common.core.command.ExecutionContext;
+import org.tizen.common.core.command.Executor;
+import org.tizen.common.ui.commandbar.command.git.*;
+import org.tizen.common.ui.commandbar.command.launcher.CommandLauncher;
+import org.tizen.common.ui.view.console.ConsoleManager;
+import org.tizen.common.util.ArrayUtil;
+import org.tizen.common.util.CollectionUtil;
+import org.tizen.common.util.ViewUtil;
+
+public class GitCommand extends ConsoleCommand {
+ public void run(final Executor executor, final ExecutionContext context) throws Exception {
+ ConsoleManager console = new ConsoleManager(CONSOLE_NAME, true);
+ context.setValue(CONTEXT_CONSOLE, console);
+ IStructuredSelection selection = (IStructuredSelection) ViewUtil.getWorkbenchWindow().getSelectionService().getSelection("org.eclipse.ui.navigator.ProjectExplorer");
+ Object firstElement = selection.getFirstElement();
+ String resource = null;
+ if (firstElement instanceof IResource) {
+ resource = ((IResource) firstElement).getLocation().toPortableString();
+ }
+ else if (firstElement instanceof IPackageFragmentRoot) {
+ resource = ((IPackageFragmentRoot) firstElement).getJavaProject().getProject().getLocation().toPortableString();
+ }
+ context.setValue(CONTEXT_RESOURCE_PATH, resource);
+
+ final String[] opts = (String[]) context.getValue(CommandLauncher.CONTEXT_ARGS);
+ if (ArrayUtil.isEmpty(opts))
+ return;
+
+ runJGitCLI(executor, context, opts);
+ }
+
+ private void runJGitCLI(final Executor executor, final ExecutionContext context, String[] opts) throws Exception {
+ ConsoleManager console = (ConsoleManager) context.getValue(CONTEXT_CONSOLE);
+
+ final PrintStream oldOut = System.out;
+ final PrintStream oldErr = System.err;
+ try {
+ PrintStream out = new PrintStream(console.getMessageConsoleStream());
+ //System.setErr(out);
+ //System.setOut(out);
+
+ JGitCLI cli = new JGitCLI();
+ String resource = (String) context.getValue(CONTEXT_RESOURCE_PATH);
+ cli.setDirectory(resource);
+ cli.setCommand(CollectionUtil.concatenate(opts, " "));
+ cli.run(out);
+ } finally {
+ //System.setErr(oldErr);
+ //System.setOut(oldOut);
+ }
+ }
+
+ /**
+ * Runs custom implementation. It's not currently used because Command Bar uses jgit-cli now.
+ *
+ * <ul>
+ * <li>git add: {@link org.tizen.common.ui.commandbar.command.git.AddCommand}
+ * <li>git reset: {@link org.tizen.common.ui.commandbar.command.git.ResetCommand}
+ * <li>git rm: {@link org.tizen.common.ui.commandbar.command.git.RmCommand}
+ * <li>git status: {@link org.tizen.common.ui.commandbar.command.git.StatusCommand}
+ * </ul>
+ *
+ * @param executor
+ * @param context
+ * @throws Exception
+ */
+ private void runCustomImpl(final Executor executor, final ExecutionContext context, String[] opts) throws Exception {
+ Map<String, Command> cmds = new HashMap<String, Command>();
+ cmds.put("add", new AddCommand());
+ cmds.put("reset", new ResetCommand());
+ cmds.put("rm", new RmCommand());
+ cmds.put("status", new StatusCommand());
+
+ Command cmd = cmds.get(opts[0]);
+ if (cmd != null)
+ cmd.run(executor, context);
+ }
+}
--- /dev/null
+/*\r
+ * Common\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:\r
+ * Changhyun Lee <changhyun1.lee@samsung.com>\r
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>\r
+ * BonYong Lee <bonyong.lee@samsung.com>\r
+ * Kangho Kim <kh5325.kim@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * Contributors:\r
+ * - S-Core Co., Ltd\r
+ *\r
+ */\r
+\r
+package org.tizen.common.ui.commandbar.command.git;\r
+\r
+import org.eclipse.jgit.api.Git;\r
+import org.eclipse.jgit.dircache.DirCache;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.tizen.common.ui.commandbar.command.launcher.CommandLauncher;\r
+\r
+public class AddCommand extends Command {\r
+ protected void run(Repository repository) throws Exception {\r
+ if (repository != null) {\r
+ Git git = new Git(repository);\r
+\r
+ String[] args = (String[]) getContextValue(CommandLauncher.CONTEXT_ARGS);\r
+ if (args.length == 1) {\r
+ print("Nothing specified, nothing added.\n");\r
+ print("Maybe you wanted to say 'git add .'?\n");\r
+ return;\r
+ }\r
+\r
+ String paths = args[1];\r
+ DirCache dirCache = git.add().addFilepattern(paths).call();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Common\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:\r
+ * Changhyun Lee <changhyun1.lee@samsung.com>\r
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>\r
+ * BonYong Lee <bonyong.lee@samsung.com>\r
+ * Kangho Kim <kh5325.kim@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * Contributors:\r
+ * - S-Core Co., Ltd\r
+ *\r
+ */\r
+\r
+package org.tizen.common.ui.commandbar.command.git;\r
+\r
+import java.io.File;\r
+\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;\r
+import org.tizen.common.core.command.ExecutionContext;\r
+import org.tizen.common.core.command.Executor;\r
+import org.tizen.common.ui.view.console.ConsoleManager;\r
+\r
+public abstract class Command implements org.tizen.common.core.command.Command {\r
+ public static final String CONTEXT_CONSOLE = "console";\r
+ public static final String CONTEXT_RESOURCE_PATH = "resource.path";\r
+\r
+ ExecutionContext context;\r
+\r
+ abstract protected void run(Repository repository) throws Exception;\r
+\r
+ protected Object getContextValue(String key) {\r
+ return context.getValue(key);\r
+ }\r
+\r
+ protected ConsoleManager getConsole() {\r
+ return (ConsoleManager) getContextValue(CONTEXT_CONSOLE);\r
+ }\r
+\r
+ protected String getResource() {\r
+ return (String) getContextValue(CONTEXT_RESOURCE_PATH);\r
+ }\r
+\r
+ @Override\r
+ public void run(Executor executor, ExecutionContext context) throws Exception {\r
+ this.context = context;\r
+ ConsoleManager console = (ConsoleManager) context.getValue(CONTEXT_CONSOLE);\r
+\r
+ FileRepositoryBuilder builder = new FileRepositoryBuilder();\r
+ Repository repository = null;\r
+ try {\r
+ repository = builder.findGitDir(new File(getResource())).build();\r
+ } catch (Exception e) {\r
+ getConsole().println("fatal: Not a git repository (or any of the parent directories): .git");\r
+ }\r
+ try {\r
+ run(repository);\r
+ } finally {\r
+ if (repository != null)\r
+ repository.close();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void undo(Executor executor, ExecutionContext context) throws Exception {\r
+ }\r
+\r
+ @Override\r
+ public Object getResult() {\r
+ return null;\r
+ }\r
+\r
+ protected void print(String line) {\r
+ getConsole().print(line);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Common\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:\r
+ * Changhyun Lee <changhyun1.lee@samsung.com>\r
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>\r
+ * BonYong Lee <bonyong.lee@samsung.com>\r
+ * Kangho Kim <kh5325.kim@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * Contributors:\r
+ * - S-Core Co., Ltd\r
+ *\r
+ */\r
+\r
+package org.tizen.common.ui.commandbar.command.git;\r
+\r
+import java.io.File;\r
+import java.io.PrintStream;\r
+import java.net.URL;\r
+\r
+import org.eclipse.jgit.pgm.Main;\r
+import org.tizen.common.ui.Activator;\r
+import org.tizen.common.util.HostUtil;\r
+import org.tizen.common.util.OSChecker;\r
+import org.tizen.common.util.PluginUtil;\r
+\r
+public class JGitCLI extends Main {\r
+ private String gitdir;\r
+ private String command;\r
+\r
+ protected void run(String[] argv) {\r
+ super.run(argv);\r
+ }\r
+\r
+ public void run(PrintStream out) throws Exception {\r
+ String origDirectory = getDirectory();\r
+ try {\r
+ if (getCommand() == null || getCommand().isEmpty()) {\r
+ // to print "The most commonly used commands are:"\r
+ setDirectory(null);\r
+ }\r
+ /*\r
+ List<String> args = new ArrayList<String>();\r
+ if (getDirectory() != null) {\r
+ args.add("--git-dir");\r
+ args.add(getDirectory() + File.separator + ".git");\r
+ }\r
+ if (getCommand() != null) {\r
+ for (String c : getCommand().split(" "))\r
+ args.add(c);\r
+ }\r
+ */\r
+\r
+ File gitPath = findGitDir();\r
+ if (gitPath == null) {\r
+ out.println("fatal: Not a git repository (or any of the parent directories): .git");\r
+ return;\r
+ }\r
+ // I'll run jgit-cli by another process:\r
+ // - To display process OutputStream in ConsoleManager\r
+ // - To prevent System.exit() codes in org.eclipse.jgit.pgm.Main\r
+ //run(args.toArray(new String[0]));\r
+ URL fileURL = PluginUtil.getFileURLinBundle(Activator.PLUGIN_ID, "lib/jgit-cli.jar");\r
+ String jarPath = fileURL.getPath();\r
+ if (OSChecker.isWindows() && jarPath.startsWith("/")) {\r
+ // /D:/common-eplugin/org.tizen.common.ui/lib/jgit-cli.jar\r
+ jarPath = jarPath.substring(1);\r
+ }\r
+ String command = String.format("java -jar %s --git-dir %s %s", jarPath, gitPath, getCommand());\r
+ String returnExecute = HostUtil.returnExecute(command, null, true);\r
+ out.println(returnExecute);\r
+ } finally {\r
+ setDirectory(origDirectory);\r
+ }\r
+ }\r
+\r
+ private File findGitDir() {\r
+ String gitPath = null;\r
+ if (getDirectory() != null) {\r
+ // org.eclipse.jgit.pgm.Main class does not use findGitDir(file). So it does not lookup upward.\r
+ gitPath = getDirectory();\r
+ while (gitPath != null) {\r
+ File f = new File(gitPath + File.separator + ".git");\r
+ if (f.exists() && f.isDirectory())\r
+ return f;\r
+ gitPath = new File(gitPath).getParent();\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public String getDirectory() {\r
+ return gitdir;\r
+ }\r
+\r
+ public void setDirectory(String gitdir) {\r
+ this.gitdir = gitdir;\r
+ }\r
+\r
+ public String getCommand() {\r
+ return command;\r
+ }\r
+\r
+ public void setCommand(String command) {\r
+ this.command = command;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Common\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:\r
+ * Changhyun Lee <changhyun1.lee@samsung.com>\r
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>\r
+ * BonYong Lee <bonyong.lee@samsung.com>\r
+ * Kangho Kim <kh5325.kim@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * Contributors:\r
+ * - S-Core Co., Ltd\r
+ *\r
+ */\r
+\r
+package org.tizen.common.ui.commandbar.command.git;\r
+\r
+import org.eclipse.jgit.api.Git;\r
+import org.eclipse.jgit.dircache.DirCache;\r
+import org.eclipse.jgit.lib.Constants;\r
+import org.eclipse.jgit.lib.Ref;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.tizen.common.ui.commandbar.command.launcher.CommandLauncher;\r
+\r
+public class ResetCommand extends Command {\r
+ protected void run(Repository repository) throws Exception {\r
+ if (repository != null) {\r
+ Git git = new Git(repository);\r
+\r
+ String[] args = (String[]) getContextValue(CommandLauncher.CONTEXT_ARGS);\r
+ if (args.length == 1) {\r
+ print("Unstaged changes after reset:\n");\r
+ // TODO:\r
+ return;\r
+ }\r
+\r
+ String paths = args[1];\r
+ git.reset().setRef(Constants.HEAD).addPath(paths).call();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Common\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:\r
+ * Changhyun Lee <changhyun1.lee@samsung.com>\r
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>\r
+ * BonYong Lee <bonyong.lee@samsung.com>\r
+ * Kangho Kim <kh5325.kim@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * Contributors:\r
+ * - S-Core Co., Ltd\r
+ *\r
+ */\r
+\r
+package org.tizen.common.ui.commandbar.command.git;\r
+\r
+import org.eclipse.jgit.api.Git;\r
+import org.eclipse.jgit.dircache.DirCache;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.tizen.common.ui.commandbar.command.launcher.CommandLauncher;\r
+\r
+public class RmCommand extends Command {\r
+ protected void run(Repository repository) throws Exception {\r
+ if (repository != null) {\r
+ Git git = new Git(repository);\r
+\r
+ String[] args = (String[]) getContextValue(CommandLauncher.CONTEXT_ARGS);\r
+ if (args.length == 1) {\r
+ return;\r
+ }\r
+\r
+ String paths = args[1];\r
+ DirCache dirCache = git.rm().addFilepattern(paths).call();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Common\r
+ *\r
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+ *\r
+ * Contact:\r
+ * Changhyun Lee <changhyun1.lee@samsung.com>\r
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>\r
+ * BonYong Lee <bonyong.lee@samsung.com>\r
+ * Kangho Kim <kh5325.kim@samsung.com>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * Contributors:\r
+ * - S-Core Co., Ltd\r
+ *\r
+ */\r
+\r
+package org.tizen.common.ui.commandbar.command.git;\r
+\r
+import static org.eclipse.jgit.lib.Constants.HEAD;\r
+\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.eclipse.jgit.api.Git;\r
+import org.eclipse.jgit.diff.DiffEntry;\r
+import org.eclipse.jgit.diff.RenameDetector;\r
+import org.eclipse.jgit.lib.ObjectId;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.lib.RepositoryState;\r
+import org.eclipse.jgit.revwalk.RevCommit;\r
+import org.eclipse.jgit.revwalk.RevWalk;\r
+import org.eclipse.jgit.treewalk.FileTreeIterator;\r
+import org.eclipse.jgit.treewalk.TreeWalk;\r
+\r
+public class StatusCommand extends Command {\r
+ private static final char DIFF_STATUS_ADDED = 'A';\r
+ private static final char DIFF_STATUS_COPIED = 'C';\r
+ private static final char DIFF_STATUS_DELETED = 'D';\r
+ private static final char DIFF_STATUS_MODIFIED = 'M';\r
+ private static final char DIFF_STATUS_RENAMED = 'R';\r
+ private static final char DIFF_STATUS_TYPE_CHANGED = 'T';\r
+ private static final char DIFF_STATUS_UNKNOWN = 'X';\r
+ private static final char DIFF_STATUS_UNMERGED = 'U';\r
+\r
+ private static final int WT_STATUS_UPDATED = 1;\r
+ private static final int WT_STATUS_CHANGED = 2;\r
+\r
+ protected void run(Repository repository) throws Exception {\r
+ if (repository != null) {\r
+ Git git = new Git(repository);\r
+ WorkingTreeStatus s = new WorkingTreeStatus(git.status().call());\r
+\r
+ prepare(repository, s);\r
+\r
+ print(repository, s);\r
+ }\r
+ }\r
+\r
+ private void print(Repository repository, WorkingTreeStatus s) {\r
+ printStatus(String.format("On branch %s\n", s.branch));\r
+ //wt_status_print_state(s, &state);\r
+ //wt_status_print_updated(s);\r
+ //wt_status_print_unmerged(s);\r
+ //wt_status_print_changed(s);\r
+ printState(s, repository.getRepositoryState());\r
+ //if (!s.is_initial)\r
+ printTracking(s);\r
+\r
+ printUpdated(s);\r
+ printChanged(s);\r
+ printOther(s, s.untracked, "Untracked files", "add");\r
+\r
+ if (!s.commitable) {\r
+ if (s.workdir_dirty) {\r
+ print("no changes added to commit (use \"git add\" and/or \"git commit -a\")\n");\r
+ }\r
+ else if (!s.untracked.isEmpty()) {\r
+ print("nothing added to commit but untracked files present (use \"git add\" to track)\n");\r
+ }\r
+ else {\r
+ print("nothing to commit, working directory clean\n");\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Currently not used since compute can be very long running.\r
+ *\r
+ * <p>Please see <a href="http://dev.eclipse.org/mhonarc/lists/jgit-dev/msg00426.html">http://dev.eclipse.org/mhonarc/lists/jgit-dev/msg00426.html</a>.\r
+ *\r
+ * @param repository\r
+ * @throws Exception\r
+ */\r
+ private void createRenameDetector(Repository repository) throws Exception {\r
+ TreeWalk tw = new TreeWalk(repository);\r
+ tw.setRecursive(true);\r
+ tw.addTree(getHead(repository).getTree());\r
+ tw.addTree(new FileTreeIterator(repository));\r
+\r
+ RenameDetector rd = new RenameDetector(repository);\r
+ rd.addAll(DiffEntry.scan(tw));\r
+\r
+ List<DiffEntry> lde = rd.compute(tw.getObjectReader(), null);\r
+ for (DiffEntry de : lde) {\r
+ if (de.getScore() >= rd.getRenameScore()) {\r
+ System.out.println("file: " + de.getOldPath() + " copied/moved to: " + de.getNewPath());\r
+ }\r
+ }\r
+ }\r
+\r
+ // from gitective\r
+ private static RevCommit getHead(final Repository repository) {\r
+ return getCommit(repository, HEAD);\r
+ }\r
+\r
+ // from gitective\r
+ private static RevCommit getCommit(final Repository repository, final String revision) {\r
+ if (repository == null)\r
+ throw new IllegalArgumentException("Repository can not be null");\r
+ if (revision == null)\r
+ throw new IllegalArgumentException("Revision can not be null");\r
+ if (revision.length() == 0)\r
+ throw new IllegalArgumentException("Revision can not be empty");\r
+\r
+ return parse(repository, resolve(repository, revision));\r
+ }\r
+\r
+ private static ObjectId resolve(final Repository repository, final String revision) {\r
+ try {\r
+ return repository.resolve(revision);\r
+ } catch (IOException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+\r
+ private static RevCommit parse(final Repository repository, final ObjectId commit) {\r
+ final RevWalk walk = new RevWalk(repository);\r
+ walk.setRetainBody(true);\r
+ try {\r
+ return walk.parseCommit(commit);\r
+ } catch (IOException e) {\r
+ throw new RuntimeException(e);\r
+ } finally {\r
+ walk.release();\r
+ }\r
+ }\r
+\r
+ private void printState(WorkingTreeStatus s, RepositoryState state) {\r
+ if (state == RepositoryState.MERGING) {\r
+ printlnStatus("merging");\r
+ }\r
+ else if (state == RepositoryState.REBASING || state == RepositoryState.REBASING_INTERACTIVE) {\r
+ printlnStatus("rebasing");\r
+ }\r
+ else if (state == RepositoryState.CHERRY_PICKING) {\r
+ printlnStatus("cherry_picking");\r
+ }\r
+ else if (state == RepositoryState.REVERTING) {\r
+ printlnStatus("reverting");\r
+ }\r
+ if (state == RepositoryState.BISECTING) {\r
+ printlnStatus("bisecting");\r
+ }\r
+ }\r
+\r
+ private void printTracking(WorkingTreeStatus s) {\r
+ }\r
+\r
+ /**\r
+ * -1 : has delete\r
+ * 0 : no change\r
+ * 1 : some change but no delete\r
+ */\r
+ private int checkWorktreeChanges(WorkingTreeStatus s) {\r
+ int changes = 0;\r
+\r
+ for (ListItem it : s.change) {\r
+ WorkingTreeStatusChangeData d = it.util;\r
+ if (d.worktree_status == 0 || d.worktree_status == DIFF_STATUS_UNMERGED)\r
+ continue;\r
+ if (changes == 0)\r
+ changes = 1;\r
+ // rm (not staged)\r
+ if (d.worktree_status == DIFF_STATUS_DELETED)\r
+ changes = -1;\r
+ }\r
+ return changes;\r
+ }\r
+\r
+ private void printUpdated(WorkingTreeStatus s) {\r
+ boolean shown_header = false;\r
+\r
+ // git rm, git add -> Changes to be committed:\r
+ for (ListItem it : s.change) {\r
+ WorkingTreeStatusChangeData d = it.util;\r
+ if (d.index_status == 0 || d.index_status == DIFF_STATUS_UNMERGED)\r
+ continue;\r
+ if (!shown_header) {\r
+ printCachedHeader(s);\r
+ s.commitable = true;\r
+ shown_header = true;\r
+ }\r
+ printChangeData(s, WT_STATUS_UPDATED, it);\r
+ }\r
+ if (shown_header)\r
+ printTrailer(s);\r
+ }\r
+\r
+ private void printCachedHeader(WorkingTreeStatus s) {\r
+ printlnStatus("Changes to be committed:");\r
+ printlnStatus(String.format(" (use \"git reset %s <file>...\" to unstage)", s.reference));\r
+ printlnStatus("");\r
+ }\r
+\r
+ private void printChanged(WorkingTreeStatus s) {\r
+ int worktree_changes = checkWorktreeChanges(s);\r
+\r
+ if (worktree_changes == 0)\r
+ return;\r
+\r
+ printDirtyHeader(s, worktree_changes < 0);\r
+\r
+ for (ListItem it : s.change) {\r
+ WorkingTreeStatusChangeData d = it.util;\r
+ if (d.worktree_status == 0 || d.worktree_status == DIFF_STATUS_UNMERGED)\r
+ continue;\r
+ printChangeData(s, WT_STATUS_CHANGED, it);\r
+ }\r
+ printTrailer(s);\r
+ }\r
+\r
+ private void printChangeData(WorkingTreeStatus s, int change_type, ListItem it) {\r
+ WorkingTreeStatusChangeData d = it.util;\r
+ int status = 0;\r
+ String one;\r
+\r
+ switch (change_type) {\r
+ case WT_STATUS_UPDATED:\r
+ status = d.index_status;\r
+ break;\r
+ case WT_STATUS_CHANGED:\r
+ // TODO: submodule\r
+ status = d.worktree_status;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ // TODO: Make relative by quote_path\r
+ one = it.path;\r
+\r
+ printStatus("\t");\r
+ switch (status) {\r
+ case DIFF_STATUS_ADDED:\r
+ printStatusMore(String.format("new file: %s", one));\r
+ break;\r
+ case DIFF_STATUS_DELETED:\r
+ printStatusMore(String.format("deleted: %s", one));\r
+ break;\r
+ case DIFF_STATUS_MODIFIED:\r
+ printStatusMore(String.format("modified: %s", one));\r
+ break;\r
+ case DIFF_STATUS_RENAMED:\r
+ // TODO: Not supported\r
+ // If we call createRenameDetector(), rename can be detected. But compute can be very long running.\r
+ // cf.)) http://stackoverflow.com/questions/17296278/jgit-detect-rename-in-working-copy/17302068\r
+ printStatusMore(String.format("renamed: %s -> %s", one));\r
+ break;\r
+ }\r
+ printStatusMore("\n");\r
+ }\r
+\r
+ private void printOther(WorkingTreeStatus s, List<ListItem> l, String what, String how) {\r
+ if (l.isEmpty())\r
+ return;\r
+\r
+ printOtherHeader(s, what, how);\r
+\r
+ for (ListItem it : l) {\r
+ printStatus(String.format("\t%s\n", it.path));\r
+ }\r
+ }\r
+\r
+ private void printOtherHeader(WorkingTreeStatus s, String what, String how) {\r
+ printlnStatus(String.format("%s:", what));\r
+ printlnStatus(String.format(" (use \"git %s <file>...\" to include in what will be committed)", how));\r
+ printlnStatus("");\r
+ }\r
+\r
+ private void printDirtyHeader(WorkingTreeStatus s, boolean hasDeleted) {\r
+ printlnStatus("Changes not staged for commit:");\r
+ if (!hasDeleted)\r
+ printlnStatus(" (use \"git add <file>...\" to update what will be committed)");\r
+ else\r
+ printlnStatus(" (use \"git add/rm <file>...\" to update what will be committed)");\r
+ printlnStatus(" (use \"git checkout -- <file>...\" to discard changes in working directory)");\r
+ //print(" (commit or discard the untracked or modified content in submodules)");\r
+ printlnStatus("");\r
+ }\r
+\r
+ private void prepare(Repository repository, WorkingTreeStatus s) {\r
+ try {\r
+ s.branch = repository.getBranch();\r
+ } catch (IOException e) {\r
+ }\r
+ s.reference = "HEAD";\r
+ }\r
+\r
+ private void printTrailer(WorkingTreeStatus s) {\r
+ printlnStatus("");\r
+ }\r
+\r
+ private void printlnStatus(String line) {\r
+ getConsole().println("# " + line);\r
+ }\r
+\r
+ private void printStatus(String line) {\r
+ getConsole().print("# " + line);\r
+ }\r
+\r
+ private void printStatusMore(String line) {\r
+ getConsole().print(line);\r
+ }\r
+\r
+ class WorkingTreeStatus {\r
+ org.eclipse.jgit.api.Status status;\r
+\r
+ String branch;\r
+ String reference;\r
+\r
+ boolean commitable;\r
+ boolean workdir_dirty;\r
+ List<ListItem> change;\r
+ List<ListItem> untracked;\r
+\r
+ public WorkingTreeStatus(org.eclipse.jgit.api.Status status) {\r
+ this.status = status;\r
+ try {\r
+ workdir_dirty = !status.isClean();\r
+ change = new ArrayList<ListItem>();\r
+ for (String path : status.getAdded()) {\r
+ change.add(new ListItem(path, new WorkingTreeStatusChangeData(0, DIFF_STATUS_ADDED)));\r
+ }\r
+ for (String path : status.getRemoved()) {\r
+ change.add(new ListItem(path, new WorkingTreeStatusChangeData(0, DIFF_STATUS_DELETED)));\r
+ }\r
+ // if you modify an existing file and call 'git add ...' on it\r
+ for (String path : status.getChanged()) {\r
+ change.add(new ListItem(path, new WorkingTreeStatusChangeData(0, DIFF_STATUS_MODIFIED)));\r
+ }\r
+ for (String path : status.getModified()) {\r
+ change.add(new ListItem(path, new WorkingTreeStatusChangeData(DIFF_STATUS_MODIFIED, 0)));\r
+ //workdir_dirty = true;\r
+ }\r
+ for (String path : status.getMissing()) {\r
+ change.add(new ListItem(path, new WorkingTreeStatusChangeData(DIFF_STATUS_DELETED, 0)));\r
+ }\r
+ untracked = new ArrayList<ListItem>();\r
+ for (String path : status.getUntracked()) {\r
+ untracked.add(new ListItem(path, new WorkingTreeStatusChangeData(0, 0)));\r
+ }\r
+ // TODO: status.getConflicting()\r
+ } catch (Exception e) {\r
+ }\r
+ }\r
+ }\r
+\r
+ class WorkingTreeStatusChangeData {\r
+ int worktree_status;\r
+ int index_status;\r
+\r
+ public WorkingTreeStatusChangeData(int worktree_status, int index_status) {\r
+ this.worktree_status = worktree_status;\r
+ this.index_status = index_status;\r
+ }\r
+ }\r
+\r
+ class ListItem {\r
+ String path;\r
+ WorkingTreeStatusChangeData util;\r
+\r
+ public ListItem(String path, WorkingTreeStatusChangeData util) {\r
+ this.path = path;\r
+ this.util = util;\r
+ }\r
+ }\r
+}\r
// TODO: need to use custom OptionValidator?\r
// opt contains illegal character value '@'\r
//result.addOption(OptionBuilder.hasArg(true).create("@q"));\r
+ addOption(result, OptionBuilder.hasArg(true).create(Commands.GIT_COMMAND), new GitCommand());\r
addOption(result, OptionBuilder.hasArg(true).create(Commands.QUERY_COMMAND), new QueryCommand());\r
result.addOption(OptionBuilder.hasArg(true).create(Commands.SHOW_COMMAND));\r
addOption(result, OptionBuilder.hasArg(true).create(Commands.SDB_COMMAND), new SdbCommand());\r