forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user