From cd041f3f93937ae0ce229a0c6c71a54ce49991b7 Mon Sep 17 00:00:00 2001
From: Petar Perisin <petar.perisin@gmail.com>
Date: Sun, 22 Sep 2013 10:19:26 +0300
Subject: [PATCH] Git: Create local branch after checkout

Change-Id: I2f9c47862304773234612250bb1e3e2e759a159e
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
---
 src/plugins/git/gitclient.cpp | 68 ++++++++++++++++++++++++++++++++---
 src/plugins/git/gitclient.h   |  2 ++
 2 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 7da73057909..764ba726b07 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -36,6 +36,7 @@
 #include "gitsubmiteditor.h"
 #include "gitversioncontrol.h"
 #include "mergetool.h"
+#include "branchadddialog.h"
 
 #include <vcsbase/submitfilemodel.h>
 
@@ -1545,12 +1546,10 @@ bool GitClient::synchronousCheckout(const QString &workingDirectory,
 {
     QByteArray outputText;
     QByteArray errorText;
-    QStringList arguments;
-    arguments << QLatin1String("checkout") << ref;
+    QStringList arguments = setupCheckoutArguments(workingDirectory, ref);
     const bool rc = fullySynchronousGit(workingDirectory, arguments, &outputText, &errorText,
                                         VcsBasePlugin::ExpectRepoChanges);
-    const QString output = commandOutputFromLocal8Bit(outputText);
-    outputWindow()->append(output);
+    outputWindow()->append(commandOutputFromLocal8Bit(outputText));
     if (!rc) {
         msgCannotRun(arguments, workingDirectory, errorText, errorMessage);
         return false;
@@ -1559,6 +1558,67 @@ bool GitClient::synchronousCheckout(const QString &workingDirectory,
     return true;
 }
 
+/* method used to setup arguments for checkout, in case user wants to create local branch */
+QStringList GitClient::setupCheckoutArguments(const QString &workingDirectory,
+                                              const QString &ref)
+{
+    QStringList arguments(QLatin1String("checkout"));
+    arguments << ref;
+
+    QStringList localBranches = synchronousRepositoryBranches(workingDirectory);
+
+    if (localBranches.contains(ref))
+        return arguments;
+
+    if (QMessageBox::question(Core::ICore::mainWindow(), tr("Create Local Branch"),
+                              tr("Would you like to create local branch?"),
+                              QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
+        return arguments;
+    }
+
+    if (synchronousCurrentLocalBranch(workingDirectory).isEmpty())
+        localBranches.removeFirst();
+
+    QString refSha;
+    if (!synchronousRevParseCmd(workingDirectory, ref, &refSha))
+        return arguments;
+
+    QString output;
+    QStringList forEachRefArgs(QLatin1String("refs/remotes/"));
+    forEachRefArgs << QLatin1String("--format=%(objectname) %(refname:short)");
+    if (!synchronousForEachRefCmd(workingDirectory, forEachRefArgs, &output))
+        return arguments;
+
+    QString remoteBranch;
+    const QString head(QLatin1String("/HEAD"));
+
+    foreach (const QString &singleRef, output.split(QLatin1Char('\n'))) {
+        if (singleRef.startsWith(refSha)) {
+            // branch name might be origin/foo/HEAD
+            if (!singleRef.endsWith(head) || singleRef.count(QLatin1Char('/')) > 1) {
+                remoteBranch = singleRef.mid(refSha.length() + 1);
+                if (remoteBranch == ref)
+                    break;
+            }
+        }
+    }
+
+    BranchAddDialog branchAddDialog(localBranches, true, Core::ICore::mainWindow());
+    branchAddDialog.setTrackedBranchName(remoteBranch, true);
+
+    if (branchAddDialog.exec() != QDialog::Accepted)
+        return arguments;
+
+    arguments.removeLast();
+    arguments << QLatin1String("-b") << branchAddDialog.branchName();
+    if (branchAddDialog.track())
+        arguments << QLatin1String("--track") << remoteBranch;
+    else
+        arguments << QLatin1String("--no-track") << ref;
+
+    return arguments;
+}
+
 void GitClient::reset(const QString &workingDirectory, const QString &argument, const QString &commit)
 {
     QStringList arguments;
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 58c7c8b24ce..f9d7f8a5fa6 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -182,6 +182,8 @@ public:
     // Checkout branch
     bool synchronousCheckout(const QString &workingDirectory, const QString &ref,
                              QString *errorMessage = 0);
+
+    QStringList setupCheckoutArguments(const QString &workingDirectory, const QString &ref);
     void updateSubmodulesIfNeeded(const QString &workingDirectory, bool prompt);
 
     // Do a stash and return identier.
-- 
GitLab