diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 638d073..c20e3bf 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -14,16 +14,32 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -name: Build (Linux, Ubuntu 18.04) +name: Build (Linux, Ubuntu) on: -- pull_request -- push + pull_request: + push: + schedule: + - cron: '0 2 * * 5' # Every Friday at 2am + workflow_dispatch: + +# Reduce permissions to minimum for security +permissions: + contents: read jobs: build: - name: Build (Linux, Ubuntu 18.04) - runs-on: ubuntu-18.04 + strategy: + fail-fast: false + matrix: + include: + - runs-on: ubuntu-24.04 + qt: qt5-qmake + - runs-on: ubuntu-22.04 + qt: qt5-qmake + + name: Build (Linux, ${{ matrix.runs-on }}) + runs-on: ${{ matrix.runs-on }} steps: - name: 'Install build dependencies' run: |- @@ -33,11 +49,12 @@ jobs: build-essential \ libapr1-dev \ libsvn-dev \ - qt5-default \ - qtbase5-dev + ${{ matrix.qt }} \ + qtbase5-dev \ + subversion - name: 'Checkout Git branch' - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: true @@ -58,3 +75,16 @@ jobs: set -e make INSTALL_ROOT="${PWD}"/ROOT install find ROOT | sort + + docker: + name: Check Dockerfile + runs-on: ubuntu-latest + steps: + - name: 'Checkout Git branch' + uses: actions/checkout@v3 + with: + submodules: true + + - name: 'Build' + run: |- + docker build . diff --git a/Dockerfile b/Dockerfile index e790744..b1c8518 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,24 @@ -FROM debian:8.11 +FROM ubuntu:22.04 -RUN apt update && apt install -y \ - make g++ libapr1-dev libsvn-dev libqt4-dev \ - git subversion \ - && rm -rf /var/lib/apt/lists/* \ - && mkdir /usr/local/svn2git +# Change locale to let svn handle international characters +ENV LC_ALL C.UTF-8 -ADD . /usr/local/svn2git +# Install dependencies +RUN apt-get update && apt-get install --yes --no-install-recommends \ + build-essential \ + libapr1-dev \ + libsvn-dev \ + qt5-qmake \ + qtbase5-dev \ + git \ + subversion \ + && rm -rf /var/lib/apt/lists/* +# Build the binary +RUN mkdir /usr/local/svn2git +ADD . /usr/local/svn2git RUN cd /usr/local/svn2git && qmake && make +# Docker interface WORKDIR /workdir CMD /usr/local/svn2git/svn-all-fast-export diff --git a/README.md b/README.md index 1e7f04c..9b48450 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Just mount your SVN folder, plus another working directory where Git repository Sample usage with input mounted in /tmp and output produced in /workdir: ``` docker build -t svn2git . -docker run --rm -it -v `pwd`/workdir:/workdir -v /var/lib/svn/project1:/tmp/svn -v `pwd`/conf:/tmp/conf svn2git /usr/local/svn2git/svn-all-fast-export --identity-map /tmp/conf/project1.authors --rules /tmp/conf/project1.rules --add-metadata --svn-branches --debug-rules --svn-ignore --empty-dirs /tmp/svn/ +docker run --rm -it -v `pwd`/workdir:/workdir -v /var/lib/svn/project1:/tmp/svn -v `pwd`/conf:/tmp/conf svn2git /usr/local/svn2git/svn-all-fast-export --identity-map /tmp/conf/project1.authors --rules /tmp/conf/project1.rules --add-metadata --svn-branches --debug-rules --svn-ignore --empty-dirs /tmp/svn/ ``` Building the tool @@ -80,6 +80,10 @@ end match ``` Creates a rule that matches paths by `REGEX` and applies some `PARAMETERS` to them. Matching groups can be created, and the values used in the parameters. +You need to make sure the regex matching a SVN directory path matches also the end slash (e.g. `./`) otherwise Git fast-import will crash with an `fatal: Empty path component found in input` errors. +For example, the rule `/project/trunk/.*/myFolder`, should become `/project/trunk/.*/myFolder/`. + + `PARAMETERS` is any number of: @@ -93,9 +97,9 @@ Creates a rule that matches paths by `REGEX` and applies some `PARAMETERS` to th - `export` I have no idea what this does - `ignore` ignores this path - - `recurse` tells svn2git to ignore this path and continue searching it's children. + - `recurse` tells svn2git to ignore this path and continue searching its children. -- `annotate true` creates annotated tags instead of lightweight tags +- `annotated true` creates annotated tags instead of lightweight tags. You can see the commit log with `git tag -n`. ### `include FILENAME` @@ -113,4 +117,4 @@ Please feel free to fill this section in. Some SVN tricks --------------- You can access your newly rsynced SVN repo with commands like `svn ls file:///path/to/repo/trunk/KDE`. -A common issue is tracking when an item left playground for kdereview and then went from kdereview to its final destination. There is no straightforward way to do this. So the following command comes in handy: `svn log -v file:///path/to/repo/kde-svn/kde/trunk/kdereview | grep /trunk/kdereview/mplayerthumbs -A 5 -B 5` This will print all commits relevant to the package you are trying to track. You can also pipe the above command to head or tail to see the the first and last commit it was in that directory. +A common issue is tracking when an item left playground for kdereview and then went from kdereview to its final destination. There is no straightforward way to do this. So the following command comes in handy: `svn log -v file:///path/to/repo/kde-svn/kde/trunk/kdereview | grep /trunk/kdereview/mplayerthumbs -A 5 -B 5` This will print all commits relevant to the package you are trying to track. You can also pipe the above command to head or tail to see the first and last commit it was in that directory. diff --git a/src/repository.cpp b/src/repository.cpp index 5fd5b24..b926ad4 100644 --- a/src/repository.cpp +++ b/src/repository.cpp @@ -113,6 +113,7 @@ class FastImportRepository : public Repository QVector marks; }; + QString defaultBranch; QHash branches; QHash branchNotes; QHash annotatedTags; @@ -326,8 +327,18 @@ FastImportRepository::FastImportRepository(const Rules::Repository &rule) branches.insert(branchRule.name, branch); } - // create the default branch - branches["master"].created = 1; + // create the defaultBranch from the config + QProcess config; + config.start("git", QStringList() << "config" << "init.defaultBranch"); + config.waitForFinished(-1); + defaultBranch = QString(config.readAllStandardOutput()).trimmed(); + + // Create the default branch + if (defaultBranch.isEmpty()) { + defaultBranch = "master"; + } + + branches[defaultBranch].created = 1; if (!CommandLineParser::instance()->contains("dry-run") && !CommandLineParser::instance()->contains("create-dump")) { fastImport.setWorkingDirectory(name); @@ -725,7 +736,7 @@ void FastImportRepository::commit() Repository::Transaction *FastImportRepository::newTransaction(const QString &branch, const QString &svnprefix, int revnum) { - if (!branches.contains(branch)) { + if (!branchExists(branch)) { qWarning() << "WARN: Transaction:" << branch << "is not a known branch in repository" << name << endl << "Going to create it automatically"; } @@ -1122,8 +1133,9 @@ int FastImportRepository::Transaction::commit() if (br.created && !br.marks.isEmpty() && br.marks.last()) { parentmark = br.marks.last(); } else { - if (revnum > 1) { - // Any branch at revision 1 isn't going to exist, so lets not alarm the user. + if (revnum > 1 && branch != repository->defaultBranch) { + // Any branch at revision 1 isn't going to exist -> do not alarm the user. + // Default branch might also not exist yet -> do not alarm the user. qWarning() << "WARN: Branch" << branch << "in repository" << repository->name << "doesn't exist at revision" << revnum << "-- did you resume from the wrong revision?"; } diff --git a/test.sh b/test.sh index 5f5d988..1a40cd8 100755 --- a/test.sh +++ b/test.sh @@ -38,4 +38,28 @@ else fi mkdir -p "$SCRIPT_DIR/build/tmp" -TMPDIR="$SCRIPT_DIR/build/tmp" test/libs/bats-core/bin/bats "$@" +{ + TMPDIR="$SCRIPT_DIR/build/tmp" \ + test/libs/bats-core/bin/bats "$@" \ + 4>&1 1>&2 2>&4 | + awk ' + BEGIN { + duplicate_test_names = "" + } + + { + print + } + + /duplicate test name/ { + duplicate_test_names = duplicate_test_names "\n\t" $0 + } + + END { + if (length(duplicate_test_names)) { + print "\nERROR: duplicate test name(s) found:" duplicate_test_names + exit 1 + } + } + ' +} 4>&1 1>&2 2>&4 diff --git a/test/empty-dirs.bats b/test/empty-dirs.bats index 8f5b20f..f07429a 100644 --- a/test/empty-dirs.bats +++ b/test/empty-dirs.bats @@ -1060,7 +1060,7 @@ load 'common' assert_equal "$(git -C git-repo show branch-a:dir-a/.gitignore)" '/ignore-a' } -@test 'branching with svn-ignore, svn-branches and empty-dirs parameter should not replace filled .gitignore files with empty ones' { +@test 'branching with svn-ignore, svn-branches and empty-dirs parameter should not replace filled .gitignore files with empty ones (nested)' { svn mkdir project-a cd project-a svn mkdir --parents trunk/dir-a