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
This commit is contained in:
Tobias Hunger
2010-10-05 10:11:36 +02:00
parent 4fc07056fd
commit cd6009c276
2 changed files with 35 additions and 15 deletions

View File

@@ -45,6 +45,7 @@ struct CloneWizardPagePrivate {
const QString gitPostFix; const QString gitPostFix;
const QString protocolDelimiter; const QString protocolDelimiter;
QCheckBox *deleteMasterCheckBox; QCheckBox *deleteMasterCheckBox;
QString headBranch;
}; };
CloneWizardPagePrivate::CloneWizardPagePrivate() : CloneWizardPagePrivate::CloneWizardPagePrivate() :
@@ -131,33 +132,32 @@ QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizardPage::createCheckoutJob(
const QString binary = client->binary(); const QString binary = client->binary();
QStringList args;
args << QLatin1String("clone") << repository() << checkoutDir;
VCSBase::ProcessCheckoutJob *job = new VCSBase::ProcessCheckoutJob; VCSBase::ProcessCheckoutJob *job = new VCSBase::ProcessCheckoutJob;
const QProcessEnvironment env = client->processEnvironment(); const QProcessEnvironment env = client->processEnvironment();
// 1) Basic checkout step // 1) Basic checkout step
QStringList args;
args << QLatin1String("clone") << repository() << checkoutDir;
job->addStep(binary, args, workingDirectory, env); job->addStep(binary, args, workingDirectory, env);
const QString checkoutBranch = branch(); const QString checkoutBranch = branch();
// 2) Checkout branch, change to checkoutDir // 2) Checkout branch, change to checkoutDir
const QString masterBranch = QLatin1String("master"); if (!checkoutBranch.isEmpty() && checkoutBranch != d->headBranch) {
if (!checkoutBranch.isEmpty() && checkoutBranch != masterBranch) {
// Create branch // Create branch
args.clear(); args.clear();
args << QLatin1String("branch") << QLatin1String("--track") args << QLatin1String("branch") << QLatin1String("--track")
<< checkoutBranch << (QLatin1String("origin/") + checkoutBranch); << checkoutBranch << (QLatin1String("origin/") + checkoutBranch);
job->addStep(binary, args, *checkoutPath, env); job->addStep(binary, args, *checkoutPath, env);
// Checkout branch // Checkout branch
args.clear(); args.clear();
args << QLatin1String("checkout") << checkoutBranch; args << QLatin1String("checkout") << checkoutBranch;
job->addStep(binary, args, *checkoutPath, env); job->addStep(binary, args, *checkoutPath, env);
// Delete master if desired if (deleteMasterBranch() && d->headBranch != QLatin1String("<detached HEAD>")) {
if (deleteMasterBranch()) { // Make sure we only have the requested branch:
args.clear(); args.clear();
args << QLatin1String("branch") << QLatin1String("-D") << masterBranch; args << QLatin1String("branch") << QLatin1String("-D") << d->headBranch;
job->addStep(binary, args, *checkoutPath, env);
} }
job->addStep(binary, args, *checkoutPath, env);
} }
return QSharedPointer<VCSBase::AbstractCheckoutJob>(job); return QSharedPointer<VCSBase::AbstractCheckoutJob>(job);
@@ -166,11 +166,16 @@ QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizardPage::createCheckoutJob(
QStringList CloneWizardPage::branches(const QString &repository, int *current) QStringList CloneWizardPage::branches(const QString &repository, int *current)
{ {
// Run git on remote repository if an URL was specified. // Run git on remote repository if an URL was specified.
*current = 0; *current = -1;
d->headBranch.clear();
if (repository.isEmpty()) if (repository.isEmpty())
return QStringList(); return QStringList();
const QStringList branches = Internal::GitPlugin::instance()->gitClient()->synchronousRepositoryBranches(repository); 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; return branches;
} }

View File

@@ -1279,22 +1279,37 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory,
} }
// Quietly retrieve branch list of remote repository URL // 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 GitClient::synchronousRepositoryBranches(const QString &repositoryURL)
{ {
QStringList arguments(QLatin1String("ls-remote")); QStringList arguments(QLatin1String("ls-remote"));
arguments << QLatin1String("--heads") << repositoryURL; arguments << repositoryURL << QLatin1String("HEAD") << QLatin1String("refs/heads/*");
const unsigned flags = const unsigned flags =
VCSBase::VCSBasePlugin::SshPasswordPrompt| VCSBase::VCSBasePlugin::SshPasswordPrompt|
VCSBase::VCSBasePlugin::SuppressStdErrInLogWindow| VCSBase::VCSBasePlugin::SuppressStdErrInLogWindow|
VCSBase::VCSBasePlugin::SuppressFailMessageInLogWindow; VCSBase::VCSBasePlugin::SuppressFailMessageInLogWindow;
const Utils::SynchronousProcessResponse resp = synchronousGit(QString(), arguments, flags); const Utils::SynchronousProcessResponse resp = synchronousGit(QString(), arguments, flags);
QStringList branches; QStringList branches;
branches << "<detached HEAD>";
QString headSha;
if (resp.result == Utils::SynchronousProcessResponse::Finished) { if (resp.result == Utils::SynchronousProcessResponse::Finished) {
// split "82bfad2f51d34e98b18982211c82220b8db049b<tab>refs/heads/master" // split "82bfad2f51d34e98b18982211c82220b8db049b<tab>refs/heads/master"
foreach(const QString &line, resp.stdOut.split(QLatin1Char('\n'))) { 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('/')); const int slashPos = line.lastIndexOf(QLatin1Char('/'));
if (slashPos != -1) const QString branchName = line.mid(slashPos + 1);
branches.push_back(line.mid(slashPos + 1)); if (slashPos != -1) {
if (line.startsWith(headSha))
branches[0] = branchName;
else
branches.push_back(branchName);
}
} }
} }
return branches; return branches;