aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaja R Harinath <harinath@hurrynot.org>2010-07-22 18:32:21 +0530
committerRaja R Harinath <harinath@hurrynot.org>2010-07-22 18:32:21 +0530
commit008b28e0f4c48de8d740c51c053020d1a36315bf (patch)
tree6acd61c923518b0f9af289f1ad81e8bf6deeb463
parentf0b31cfe9d31421b83507316d1274d191336a1f7 (diff)
downloadsvn2git-008b28e0f4c48de8d740c51c053020d1a36315bf.tar
svn2git-008b28e0f4c48de8d740c51c053020d1a36315bf.tar.gz
svn2git-008b28e0f4c48de8d740c51c053020d1a36315bf.tar.bz2
svn2git-008b28e0f4c48de8d740c51c053020d1a36315bf.tar.xz
svn2git-008b28e0f4c48de8d740c51c053020d1a36315bf.zip
Provide a way to merge repositories
Suppose you have multiple repositories in SVN that you want to merge into a single one in GIT, it can get very messy to handle all the special-case rules. Instead, we introduce a new "forwarding repository" concept, which looks like repository subordinate repository unified prefix foo/ end repository This forwards all commits on the "subordinate" SVN tree to the "unified" GIT tree, with each file prefixed with "foo/".
-rw-r--r--src/main.cpp2
-rw-r--r--src/repository.cpp62
-rw-r--r--src/repository.h1
-rw-r--r--src/ruleparser.cpp8
-rw-r--r--src/ruleparser.h3
5 files changed, 73 insertions, 3 deletions
diff --git a/src/main.cpp b/src/main.cpp
index ff11255..3feb3cf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -124,6 +124,8 @@ int main(int argc, char **argv)
int min_rev = 1;
foreach (Rules::Repository rule, rules.repositories()) {
Repository *repo = makeRepository(rule, repositories);
+ if (!repo)
+ return EXIT_FAILURE;
repositories.insert(rule.name, repo);
int repo_next = repo->setupIncremental(cutoff);
diff --git a/src/repository.cpp b/src/repository.cpp
index f5b7a50..760fc1a 100644
--- a/src/repository.cpp
+++ b/src/repository.cpp
@@ -123,6 +123,59 @@ private:
Q_DISABLE_COPY(FastImportRepository)
};
+class PrefixingRepository : public Repository
+{
+ Repository *repo;
+ QString prefix;
+public:
+ class Transaction : public Repository::Transaction
+ {
+ Q_DISABLE_COPY(Transaction)
+
+ Repository::Transaction *txn;
+ QString prefix;
+ public:
+ Transaction(Repository::Transaction *t, const QString &p) : txn(t), prefix(p) {}
+ ~Transaction() { delete txn; }
+ void commit() { txn->commit(); }
+
+ void setAuthor(const QByteArray &author) { txn->setAuthor(author); }
+ void setDateTime(uint dt) { txn->setDateTime(dt); }
+ void setLog(const QByteArray &log) { txn->setLog(log); }
+
+ void noteCopyFromBranch (const QString &prevbranch, int revFrom)
+ { txn->noteCopyFromBranch(prevbranch, revFrom); }
+
+ void deleteFile(const QString &path) { txn->deleteFile(prefix + path); }
+ QIODevice *addFile(const QString &path, int mode, qint64 length)
+ { return txn->addFile(prefix + path, mode, length); }
+ };
+
+ PrefixingRepository(Repository *r, const QString &p) : repo(r), prefix(p) {}
+
+ int setupIncremental(int &) { return 1; }
+ void restoreLog() {}
+
+ int createBranch(const QString &branch, int revnum,
+ const QString &branchFrom, int revFrom)
+ { return repo->createBranch(branch, revnum, branchFrom, revFrom); }
+
+ int deleteBranch(const QString &branch, int revnum)
+ { return repo->deleteBranch(branch, revnum); }
+
+ Repository::Transaction *newTransaction(const QString &branch, const QString &svnprefix, int revnum)
+ {
+ Repository::Transaction *t = repo->newTransaction(branch, svnprefix, revnum);
+ return new Transaction(t, prefix);
+ }
+
+ void createAnnotatedTag(const QString &name, const QString &svnprefix, int revnum,
+ const QByteArray &author, uint dt,
+ const QByteArray &log)
+ { repo->createAnnotatedTag(name, svnprefix, revnum, author, dt, log); }
+ void finalizeTags() { /* loop that called this will invoke it on 'repo' too */ }
+};
+
class ProcessCache: QLinkedList<FastImportRepository *>
{
public:
@@ -151,7 +204,14 @@ static ProcessCache processCache;
Repository *makeRepository(const Rules::Repository &rule, const QHash<QString, Repository *> &repositories)
{
- return new FastImportRepository(rule);
+ if (rule.forwardTo.isEmpty())
+ return new FastImportRepository(rule);
+ Repository *r = repositories[rule.forwardTo];
+ if (!r) {
+ qCritical() << "no repository with name" << rule.forwardTo << "found at line" << rule.lineNumber;
+ return r;
+ }
+ return new PrefixingRepository(r, rule.prefix);
}
FastImportRepository::FastImportRepository(const Rules::Repository &rule)
diff --git a/src/repository.h b/src/repository.h
index 590ef0e..e07d184 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -49,7 +49,6 @@ public:
virtual void restoreLog() = 0;
virtual ~Repository() {}
- virtual void reloadBranches() = 0;
virtual int createBranch(const QString &branch, int revnum,
const QString &branchFrom, int revFrom) = 0;
virtual int deleteBranch(const QString &branch, int revnum) = 0;
diff --git a/src/ruleparser.cpp b/src/ruleparser.cpp
index 42334b7..d1f5cd4 100644
--- a/src/ruleparser.cpp
+++ b/src/ruleparser.cpp
@@ -81,7 +81,13 @@ void Rules::load()
repo.branches += branch;
continue;
- } else if (line == "end repository") {
+ } else if (matchRepoLine.exactMatch(line)) {
+ repo.forwardTo = matchRepoLine.cap(1);
+ continue;
+ } else if (matchPrefixLine.exactMatch(line)) {
+ repo.prefix = matchPrefixLine.cap(1);
+ continue;
+ } else if (line == "end repository") {
m_repositories += repo;
{
// clear out 'repo'
diff --git a/src/ruleparser.h b/src/ruleparser.h
index 8d0fcb2..95a508f 100644
--- a/src/ruleparser.h
+++ b/src/ruleparser.h
@@ -36,6 +36,9 @@ public:
QList<Branch> branches;
int lineNumber;
+ QString forwardTo;
+ QString prefix;
+
Repository() : lineNumber(0) { }
};