aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/repository.cpp26
-rw-r--r--src/repository.h1
-rw-r--r--src/svn.cpp63
3 files changed, 67 insertions, 23 deletions
diff --git a/src/repository.cpp b/src/repository.cpp
index 5250f71..847771f 100644
--- a/src/repository.cpp
+++ b/src/repository.cpp
@@ -141,7 +141,7 @@ void Repository::createBranch(const QString &branch, int revnum,
branchRef.prepend("refs/heads/");
Branch &br = branches[branch];
- if (br.created && br.created != revnum) {
+ if (br.created && br.created != revnum && br.marks.last()) {
QByteArray backupBranch = branchRef + '_' + QByteArray::number(revnum);
qWarning() << branch << "already exists; backing up to" << backupBranch;
@@ -193,6 +193,30 @@ void Repository::createBranch(const QString &branch, int revnum,
+ "\n\n");
}
+void Repository::deleteBranch(const QString &branch, int revnum)
+{
+ QByteArray branchRef = branch.toUtf8();
+ if (!branchRef.startsWith("refs/"))
+ branchRef.prepend("refs/heads/");
+
+ Branch &br = branches[branch];
+ if (br.created && br.created != revnum && br.marks.last()) {
+ QByteArray backupBranch = branchRef + '_' + QByteArray::number(revnum);
+ qWarning() << "backing up branch" << branch << "to" << backupBranch;
+
+ fastImport.write("reset " + backupBranch + "\nfrom " + branchRef + "\n\n");
+ }
+
+ br.created = revnum;
+ br.commits.append(revnum);
+ br.marks.append(0);
+
+ static QByteArray null_sha(40, '0');
+ fastImport.write("reset " + branchRef + "\nfrom " + null_sha + "\n\n"
+ "progress SVN r" + QByteArray::number(revnum)
+ + " branch " + branch.toUtf8() + " = :0 # delete\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 f30b49f..65802bb 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -65,6 +65,7 @@ public:
void reloadBranches();
void createBranch(const QString &branch, int revnum,
const QString &branchFrom, int revFrom);
+ void deleteBranch(const QString &branch, int revnum);
Transaction *newTransaction(const QString &branch, const QString &svnprefix, int revnum);
void createAnnotatedTag(const QString &name, const QString &svnprefix, int revnum,
diff --git a/src/svn.cpp b/src/svn.cpp
index d29328a..69f91af 100644
--- a/src/svn.cpp
+++ b/src/svn.cpp
@@ -509,7 +509,6 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change
svn_boolean_t is_dir;
SVN_ERR(svn_fs_is_dir(&is_dir, fs_root, key, revpool));
if (is_dir) {
- current += '/';
if (change->change_kind == svn_fs_path_change_modify ||
change->change_kind == svn_fs_path_change_add) {
if (path_from == NULL) {
@@ -520,8 +519,6 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change
}
qDebug() << " " << key << "was copied from" << path_from << "rev" << rev_from;
- } else if (change->change_kind == svn_fs_path_change_delete) {
- qDebug() << " " << key << "was deleted";
} else if (change->change_kind == svn_fs_path_change_replace) {
if (path_from == NULL)
qDebug() << " " << key << "was replaced";
@@ -531,11 +528,17 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change
qCritical() << " " << key << "was reset, panic!";
return EXIT_FAILURE;
} else {
+ // if change_kind == delete, it shouldn't come into this arm of the 'is_dir' test
qCritical() << " " << key << "has unhandled change kind " << change->change_kind << ", panic!";
return EXIT_FAILURE;
}
+ } else if (change->change_kind == svn_fs_path_change_delete) {
+ is_dir = wasDir(fs, revnum - 1, key, revpool);
}
+ if (is_dir)
+ current += '/';
+
// find the first rule that matches this pathname
MatchRuleList::ConstIterator match = findMatchRule(matchRules, revnum, current);
if (match != matchRules.constEnd()) {
@@ -546,6 +549,9 @@ int SvnRevision::exportEntry(const char *key, const svn_fs_path_change_t *change
if (is_dir && path_from != NULL) {
qDebug() << current << "is a copy-with-history, auto-recursing";
return recurse(key, change, path_from, rev_from, changes, revpool);
+ } else if (is_dir && change->change_kind == svn_fs_path_change_delete) {
+ qDebug() << current << "deleted, auto-recursing";
+ return recurse(key, change, path_from, rev_from, changes, revpool);
} else if (wasDir(fs, revnum - 1, key, revpool)) {
qDebug() << current << "was a directory; ignoring";
} else if (change->change_kind == svn_fs_path_change_delete) {
@@ -576,7 +582,14 @@ int SvnRevision::exportDispatch(const char *key, const svn_fs_path_change_t *cha
return recurse(key, change, path_from, rev_from, changes, pool);
case Rules::Match::Export:
- return exportInternal(key, change, path_from, rev_from, current, rule);
+ if (exportInternal(key, change, path_from, rev_from, current, rule) == EXIT_SUCCESS)
+ return EXIT_SUCCESS;
+ if (change->change_kind != svn_fs_path_change_delete)
+ return EXIT_FAILURE;
+ // we know that the default action inside recurse is to recurse further or to ignore,
+ // either of which is reasonably safe for deletion
+ qWarning() << "deleting unknown path" << current << "; auto-recursing";
+ return recurse(key, change, path_from, rev_from, changes, pool);
}
// never reached
@@ -590,16 +603,30 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
QString svnprefix, repository, branch, path;
splitPathName(rule, current, &svnprefix, &repository, &branch, &path);
+ Repository *repo = repositories.value(repository, 0);
+ if (!repo) {
+ if (change->change_kind != svn_fs_path_change_delete)
+ qCritical() << "Rule" << rule
+ << "references unknown repository" << repository;
+ return EXIT_FAILURE;
+ }
+
printf(".");
fflush(stdout);
// qDebug() << " " << qPrintable(current) << "rev" << revnum << "->"
// << qPrintable(repository) << qPrintable(branch) << qPrintable(path);
+ if (change->change_kind == svn_fs_path_change_delete && current == svnprefix) {
+ qDebug() << "repository" << repository << "branch" << branch << "deleted";
+ repo->deleteBranch(branch, revnum);
+ return EXIT_SUCCESS;
+ }
+
QString previous;
QString prevsvnprefix, prevrepository, prevbranch, prevpath;
if (path_from != NULL) {
- QString previous = QString::fromUtf8(path_from) + '/';
+ previous = QString::fromUtf8(path_from) + '/';
MatchRuleList::ConstIterator prevmatch =
findMatchRule(matchRules, rev_from, previous, NoIgnoreRule);
if (prevmatch != matchRules.constEnd())
@@ -634,12 +661,6 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
<< qPrintable(branch) << "is branching from"
<< qPrintable(prevbranch);
}
- Repository *repo = repositories.value(repository, 0);
- if (!repo) {
- qCritical() << "Rule" << rule
- << "references unknown repository" << repository;
- return EXIT_FAILURE;
- }
repo->createBranch(branch, revnum, prevbranch, rev_from);
if (rule.annotate) {
@@ -651,16 +672,8 @@ int SvnRevision::exportInternal(const char *key, const svn_fs_path_change_t *cha
return EXIT_SUCCESS;
}
}
-
Repository::Transaction *txn = transactions.value(repository + branch, 0);
if (!txn) {
- Repository *repo = repositories.value(repository, 0);
- if (!repo) {
- qCritical() << "Rule" << rule
- << "references unknown repository" << repository;
- return EXIT_FAILURE;
- }
-
txn = repo->newTransaction(branch, svnprefix, revnum);
if (!txn)
return EXIT_FAILURE;
@@ -695,6 +708,10 @@ int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change,
const char *path_from, svn_revnum_t rev_from,
apr_hash_t *changes, apr_pool_t *pool)
{
+ svn_fs_root_t *fs_root = this->fs_root;
+ if (change->change_kind == svn_fs_path_change_delete)
+ SVN_ERR(svn_fs_revision_root(&fs_root, fs, revnum - 1, pool));
+
// get the dir listing
apr_hash_t *entries;
SVN_ERR(svn_fs_dir_entries(&entries, fs_root, path, pool));
@@ -735,9 +752,11 @@ int SvnRevision::recurse(const char *path, const svn_fs_path_change_t *change,
rev_from, changes, current, *match, dirpool) == EXIT_FAILURE)
return EXIT_FAILURE;
} else {
- qCritical() << current << "rev" << revnum
- << "did not match any rules; cannot continue";
- return EXIT_FAILURE;
+ qDebug() << current << "rev" << revnum
+ << "did not match any rules; auto-recursing";
+ if (recurse(entry, change, entryFrom.isNull() ? 0 : entryFrom.constData(),
+ rev_from, changes, dirpool) == EXIT_FAILURE)
+ return EXIT_FAILURE;
}
}