From cd6009c276b94db65d354bb6b0037565bf7a47c3 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 5 Oct 2010 10:11:36 +0200 Subject: [PATCH] Git: Handle unusual HEADs Handle detached HEADs as well as cloning from repositories that default to another branch but master. This is relevant when clonig local repositories. Reviewed-by: Friedemann Kleint --- src/plugins/git/clonewizardpage.cpp | 29 +++++++++++++++++------------ src/plugins/git/gitclient.cpp | 21 ++++++++++++++++++--- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/plugins/git/clonewizardpage.cpp b/src/plugins/git/clonewizardpage.cpp index ea0b762421a..0cbac9ca77b 100644 --- a/src/plugins/git/clonewizardpage.cpp +++ b/src/plugins/git/clonewizardpage.cpp @@ -45,6 +45,7 @@ struct CloneWizardPagePrivate { const QString gitPostFix; const QString protocolDelimiter; QCheckBox *deleteMasterCheckBox; + QString headBranch; }; CloneWizardPagePrivate::CloneWizardPagePrivate() : @@ -131,33 +132,32 @@ QSharedPointer CloneWizardPage::createCheckoutJob( const QString binary = client->binary(); - QStringList args; - args << QLatin1String("clone") << repository() << checkoutDir; - VCSBase::ProcessCheckoutJob *job = new VCSBase::ProcessCheckoutJob; const QProcessEnvironment env = client->processEnvironment(); + // 1) Basic checkout step + QStringList args; + args << QLatin1String("clone") << repository() << checkoutDir; job->addStep(binary, args, workingDirectory, env); const QString checkoutBranch = branch(); // 2) Checkout branch, change to checkoutDir - const QString masterBranch = QLatin1String("master"); - if (!checkoutBranch.isEmpty() && checkoutBranch != masterBranch) { + if (!checkoutBranch.isEmpty() && checkoutBranch != d->headBranch) { // Create branch args.clear(); args << QLatin1String("branch") << QLatin1String("--track") - << checkoutBranch << (QLatin1String("origin/") + checkoutBranch); + << checkoutBranch << (QLatin1String("origin/") + checkoutBranch); job->addStep(binary, args, *checkoutPath, env); // Checkout branch args.clear(); args << QLatin1String("checkout") << checkoutBranch; job->addStep(binary, args, *checkoutPath, env); - // Delete master if desired - if (deleteMasterBranch()) { + if (deleteMasterBranch() && d->headBranch != QLatin1String("")) { + // Make sure we only have the requested branch: args.clear(); - args << QLatin1String("branch") << QLatin1String("-D") << masterBranch; - job->addStep(binary, args, *checkoutPath, env); + args << QLatin1String("branch") << QLatin1String("-D") << d->headBranch; } + job->addStep(binary, args, *checkoutPath, env); } return QSharedPointer(job); @@ -166,11 +166,16 @@ QSharedPointer CloneWizardPage::createCheckoutJob( QStringList CloneWizardPage::branches(const QString &repository, int *current) { // Run git on remote repository if an URL was specified. - *current = 0; + *current = -1; + d->headBranch.clear(); + if (repository.isEmpty()) return QStringList(); const QStringList branches = Internal::GitPlugin::instance()->gitClient()->synchronousRepositoryBranches(repository); - *current = branches.indexOf(QLatin1String("master")); + if (!branches.isEmpty()) { + *current = 0; // default branch is always returned first! + d->headBranch = branches.at(0); + } return branches; } diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 9837b7c35a7..3e72a4e52ce 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -1279,22 +1279,37 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, } // Quietly retrieve branch list of remote repository URL +// +// The branch HEAD is pointing to is always returned first. QStringList GitClient::synchronousRepositoryBranches(const QString &repositoryURL) { QStringList arguments(QLatin1String("ls-remote")); - arguments << QLatin1String("--heads") << repositoryURL; + arguments << repositoryURL << QLatin1String("HEAD") << QLatin1String("refs/heads/*"); const unsigned flags = VCSBase::VCSBasePlugin::SshPasswordPrompt| VCSBase::VCSBasePlugin::SuppressStdErrInLogWindow| VCSBase::VCSBasePlugin::SuppressFailMessageInLogWindow; const Utils::SynchronousProcessResponse resp = synchronousGit(QString(), arguments, flags); QStringList branches; + branches << ""; + QString headSha; if (resp.result == Utils::SynchronousProcessResponse::Finished) { // split "82bfad2f51d34e98b18982211c82220b8db049brefs/heads/master" foreach(const QString &line, resp.stdOut.split(QLatin1Char('\n'))) { + if (line.endsWith("\tHEAD")) { + Q_ASSERT(headSha.isNull()); + headSha = line.left(line.indexOf(QChar('\t'))); + continue; + } + const int slashPos = line.lastIndexOf(QLatin1Char('/')); - if (slashPos != -1) - branches.push_back(line.mid(slashPos + 1)); + const QString branchName = line.mid(slashPos + 1); + if (slashPos != -1) { + if (line.startsWith(headSha)) + branches[0] = branchName; + else + branches.push_back(branchName); + } } } return branches;