aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago@cassini.local.lan>2007-12-24 15:10:27 -0200
committerThiago Macieira <thiago@cassini.local.lan>2007-12-24 15:10:27 -0200
commitc338ae370e45e0b3d16253b9dd69c06c716e5597 (patch)
tree650bfbdf49018deee0a0baf39b6e00bcf4935328 /src
parentf97a8dff0675251aadc60d1c06ce5315eae2c36b (diff)
downloadsvn2git-c338ae370e45e0b3d16253b9dd69c06c716e5597.tar
svn2git-c338ae370e45e0b3d16253b9dd69c06c716e5597.tar.gz
svn2git-c338ae370e45e0b3d16253b9dd69c06c716e5597.tar.bz2
svn2git-c338ae370e45e0b3d16253b9dd69c06c716e5597.tar.xz
svn2git-c338ae370e45e0b3d16253b9dd69c06c716e5597.zip
Add support for branch creation on-the-fly
Diffstat (limited to 'src')
-rw-r--r--src/repository.cpp30
-rw-r--r--src/repository.h2
-rw-r--r--src/svn.cpp104
3 files changed, 113 insertions, 23 deletions
diff --git a/src/repository.cpp b/src/repository.cpp
index 05f01e1..08a5306 100644
--- a/src/repository.cpp
+++ b/src/repository.cpp
@@ -76,6 +76,36 @@ void Repository::reloadBranches()
}
}
+void Repository::createBranch(const QString &branch, int revnum,
+ const QString &branchFrom, int)
+{
+ if (!branches.contains(branch)) {
+ qCritical() << branch << "is not a known branch in repository" << name;
+ exit(1);
+ }
+
+ startFastImport();
+ QByteArray branchRef = branch.toUtf8();
+ if (!branchRef.startsWith("refs/"))
+ branchRef.prepend("refs/heads/");
+
+ Branch &br = branches[branch];
+ if (br.isCreated) {
+ QByteArray backupBranch = branchRef + '_' + QByteArray::number(revnum);
+ qWarning() << branch << "already exists; backing up to" << backupBranch;
+
+ fastImport.write("reset " + backupBranch + "\nfrom " + branchRef + "\n\n");
+ }
+
+ // now create the branch
+ br.isCreated = true;
+ QByteArray branchFromRef = branchFrom.toUtf8();
+ if (!branchFromRef.startsWith("refs/"))
+ branchFromRef.prepend("refs/heads/");
+
+ fastImport.write("reset " + branchRef + "\nfrom " + branchFromRef + "\n\n");
+}
+
Repository::Transaction *Repository::newTransaction(const QString &branch, const QString &svnprefix,
int revnum)
{
diff --git a/src/repository.h b/src/repository.h
index 4160d3f..b6b0708 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -63,6 +63,8 @@ public:
~Repository();
void reloadBranches();
+ void createBranch(const QString &branch, int revnum,
+ const QString &branchFrom, int revFrom);
Transaction *newTransaction(const QString &branch, const QString &svnprefix, int revnum);
private:
diff --git a/src/svn.cpp b/src/svn.cpp
index 3611713..3d1b693 100644
--- a/src/svn.cpp
+++ b/src/svn.cpp
@@ -178,6 +178,27 @@ findMatchRule(const MatchRuleList &matchRules, int revnum, const QString &curren
return end;
}
+static void splitPathName(const Rules::Match &rule, const QString &pathName, QString *svnprefix_p,
+ QString *repository_p, QString *branch_p, QString *path_p)
+{
+ QString svnprefix = pathName;
+ svnprefix.truncate(rule.rx.matchedLength());
+ if (svnprefix_p)
+ *svnprefix_p = svnprefix;
+
+ if (repository_p) {
+ *repository_p = svnprefix;
+ repository_p->replace(rule.rx, rule.repository);
+ }
+
+ if (branch_p) {
+ *branch_p = svnprefix;
+ branch_p->replace(rule.rx, rule.branch);
+ }
+
+ if (path_p)
+ *path_p = pathName.mid(svnprefix.length());
+}
static int pathMode(svn_fs_root_t *fs_root, const char *pathname, apr_pool_t *pool)
{
@@ -263,6 +284,8 @@ static int recursiveDumpDir(Repository::Transaction *txn, svn_fs_root_t *fs_root
if (recursiveDumpDir(txn, fs_root, entryName, entryFinalName, dirpool) == EXIT_FAILURE)
return EXIT_FAILURE;
} else if (dirent->kind == svn_node_file) {
+ printf("+");
+ fflush(stdout);
if (dumpBlob(txn, fs_root, entryName, entryFinalName, dirpool) == EXIT_FAILURE)
return EXIT_FAILURE;
}
@@ -334,6 +357,8 @@ int SvnPrivate::exportRevision(int revnum)
}
QString current = QString::fromUtf8(key);
+ if (is_dir)
+ current += '/';
// find the first rule that matches this pathname
MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current);
@@ -343,18 +368,55 @@ int SvnPrivate::exportRevision(int revnum)
// ignore rule
qDebug() << " " << qPrintable(current) << "rev" << revnum
<< "-> ignored (rule line" << rule.lineNumber << ")";
- break;
+ continue;
} else {
- QString svnprefix = current;
- svnprefix.truncate(rule.rx.matchedLength());
-
- QString repository = svnprefix;
- QString branch = svnprefix;
- QString path = current.mid(rule.rx.matchedLength());
-
- // do the replacement
- repository.replace(rule.rx, rule.repository);
- branch.replace(rule.rx, rule.branch);
+ QString svnprefix, repository, branch, path;
+ splitPathName(rule, current, &svnprefix, &repository, &branch, &path);
+
+ if (path.isEmpty() && path_from != NULL) {
+ QString previous = QString::fromUtf8(path_from) + '/';
+ MatchRuleList::ConstIterator prevmatch =
+ findMatchRule(matchRules, rev_from, previous);
+ if (prevmatch != matchRules.constEnd()) {
+ QString prevsvnprefix, prevrepository, prevbranch, prevpath;
+ splitPathName(*prevmatch, previous, &prevsvnprefix, &prevrepository,
+ &prevbranch, &prevpath);
+
+ if (!prevpath.isEmpty()) {
+ qDebug() << qPrintable(current) << "is a partial branch of repository"
+ << qPrintable(prevrepository) << "branch"
+ << qPrintable(prevbranch) << "subdir"
+ << qPrintable(prevpath);
+ } else if (prevrepository != repository) {
+ qWarning() << qPrintable(current) << "rev" << revnum
+ << "is a cross-repository copy (from repository"
+ << qPrintable(prevrepository) << "branch"
+ << qPrintable(prevbranch) << "path"
+ << qPrintable(prevpath) << "rev" << rev_from << ")";
+ } else if (prevbranch == branch) {
+ // same branch and same repository
+ qDebug() << qPrintable(current) << "rev" << revnum
+ << "is an SVN rename from"
+ << qPrintable(previous) << "rev" << rev_from;
+ continue;
+ } else {
+ // same repository but not same branch
+ // this means this is a plain branch
+ qDebug() << qPrintable(repository) << ": branch"
+ << qPrintable(branch) << "is branching from"
+ << qPrintable(prevbranch);
+
+ Repository *repo = repositories.value(repository, 0);
+ if (!repo) {
+ qCritical() << "Rule" << rule.rx.pattern() << "line" << rule.lineNumber
+ << "references unknown repository" << repository;
+ return EXIT_FAILURE;
+ }
+
+ repo->createBranch(branch, revnum, prevbranch, rev_from);
+ }
+ }
+ }
printf(".");
fflush(stdout);
@@ -385,21 +447,17 @@ int SvnPrivate::exportRevision(int revnum)
else
recursiveDumpDir(txn, fs_root, key, path, revpool);
- break;
+ continue;
}
- } else if (is_dir && path_from != NULL) {
- qDebug() << current << "is probably a new branch";
}
- if (match == matchRules.constEnd()) {
- if (is_dir) {
- qDebug() << current << "is a new directory; ignoring";
- } else if (wasDir(fs, revnum - 1, key, pool)) {
- qDebug() << current << "was a directory; ignoring";
- } else {
- qCritical() << current << "did not match any rules; cannot continue";
- return EXIT_FAILURE;
- }
+ if (is_dir) {
+ qDebug() << current << "is a new directory; ignoring";
+ } else if (wasDir(fs, revnum - 1, key, pool)) {
+ qDebug() << current << "was a directory; ignoring";
+ } else {
+ qCritical() << current << "did not match any rules; cannot continue";
+ return EXIT_FAILURE;
}
}
revpool.clear();