Are multiple repositories supported under gitlab?

svn server: /project1, /project2, …

The subgit-bitbucket plugin is mirroring each project happily.

When I tried to do this manually for subgit, when I tried to configure the second repository it told me subgit was already installed. I don’t have the instance any more to see the exact problem now.

Before I try to repeat the experiment I wanted to know if it is supposed to be possible, because I noticed that unlike some of the other subgit documentation, “import to gitlab” only seems to talk about one repository.

Hi Oliver,

basically, both SVN Mirror and SubGit have the same functionality and work with the SVN the same way, so SubGit is definitely able to mirror those projects in case if SVN Mirror add-on has already set this way.
SubGit may report that it’s already installed if subgit configure is invoked against a repository that already contains SubGit metadata. So if, for example, you are trying to install SubGit in a Bitbucket repository already covered by SVN Mirror add-on, then such a message is expected. If, on the other hand, you are trying just to establish two different mirrors – one with SVN Mirror and another with SubGit – of a single SVN project or repository, then it’s perfectly possible, yet it’s not completely clear for me how had it happened a target SubGit repository already has SubGit metadata.
In fact, most of our documentation talks about one repository, not only “Import to GitLab”. The thing is that SubGit supports two different mirror modes, local and remote, the former of which is obsolete and not recommended for production use. The GitLab manual describes the remote mode where SubGit is installed into a single Git repository, mirrors a single SVN repository or project and the SVN repository is accessed remotely even it resides on the same computer – in contrast to SubGit’s local mode where SubGit is installed into the SVN repository, accesses the SVN repository and its database directly and mirrors all the projects in this repository at once and all the target Git repositories reside right inside the SVN repository. SVN Mirror, in its turn, is only able to run remote mirrors, just by its nature.
So if you are trying to mirror some SVN repositories/projects both with SVN Mirror add-on and with SubGit at the same time, then yes, it’s perfectly possible, even if SubGit’s mirror is planned to be of the local kind (yet I wouldn’t recommend using local mode). The subgit is already installed appears when the target repository (SVN or Git depending on the setup kind) already contains SubGit metadata; and the GitLab guide describes the remote setup which is essential for GitLab and Bitbucket and is the recommended mirror mode for all new mirrors.
Hope I managed to make it clearer a bit.

Hi, @ildar.khusainov: the gitlab instance is completely separate from both the svn server and the bitbucket.

Here is the problem I am seeing:

  • configure → install → register’d 4 project paths from ${proto}://svn.host/… into separate proj.gits on the git separate git machine.

  • subgit does not resume fetching automatically after a reboot,

  • polling only resumes if I run subgit register on one of the git folders,

  • I am not using a shared daemon, as I couldn’t determine from the documentation if this was appropriate

Hi Oliver,

SubGit does not resume the synchronization automatically after the system reboot, indeed, it just has no means to add itself to the system autostart, so this should be done manually, by adding subgit install REPO or subgit fetch REPO in the system startup scripts for every mirrored repository, for example. Using those commands, actually, is the right way to start the daemon explicitly; but the daemon can also be started implicitly on a next push to a mirrored repository.
The shared daemon is definitely an appropriate way, too – in fact, it is the same SubGit daemon, but in a mode allowing to handle more than one repository. In a default SubGit setup (with no shared daemon) SubGit will start a separate daemon process for every mirrored repository; with the shared daemon it’s one process for several repositories. This approach has some benefits – it requires less resources for the daemon as it’s only one process – as well as some drawbacks – for example, if a single shared daemon handles too many repositories, then it may be required to extend the polling period. It’s up to you to decide which approach to use, they both are equal from the SubGit operations point of view only differing in the configuration; and I must note here that the shared daemon has no means to autostart either, so start the shared daemon after the system restart should be configuration manually, too.

1 Like

It turns out the issue was that I’m using “sudo subgit register”, which results in git objects in the repository that are root.root, later on attempts to start subgit fail when they can’t create git objects because the hash.git/objects/nn/nn folder is not writable to them.

@ildar.khusainov I see the docs on the rest api, but could find nothing about actually setting up such a daemon.

It seems like you just need to give them all the same pidFile path (e.,g /var/run/subgit-daemon.pid) but it would be nice to be able to confirm this by reading the docs rather than having to ask :)

Well, I thought I had it working, but with 3.3.13 it only works with the last repository you install.

I set all 5 repositories to use /var/opt/gitlab/git-data/subgit/daemon/daemon.pid ( after creating the directory ). Then I ran subgit install on each of them to update their config, and then ran a subgit config on the last path I’d installed.

When I rebooted, I tried to subgit fetch --async $repos for all of them, and all but the last one failed.

So then I tried

for repo in $(get-repos); do
   subgit install $repos
   subgit fetch --async $repos
done

the flaw in this plan is … each install kills the already running shared daemon.

So I figure I’m missing something?

If this is unclear, I can try and set up a branch of the docker container I used for the svn+ssh issue?

Hello Oliver,

It turns out the issue was that I’m using “sudo subgit register”, which results in git objects…

That is pretty strange since the register command is supposed to run on behalf of root since it needs to write to /etc but it’s not supposed to create any references in the repository, we’ll check this out.
I’m afraid setting the same pid for different repositories is not the correct way to set the shared daemon; in fact, the only needed option to configure it is the directory in the daemon “shared” section:

[daemon “shared”]
    directory = PATH

Here is the procedure to configure several repositories with the same shared daemon:

  • configure new mirrored repositories:

    subgit configure --svn-url SVN_URL_1 --shared-daemon /shared/daemon/dir repo1.git
    subgit configure --svn-url SVN_URL_2 --shared-daemon /shared/daemon/dir repo2.git
    subgit configure --svn-url SVN_URL_3 --shared-daemon /shared/daemon/dir repo3.git
    ...
    subgit configure --svn-url SVN_URL_N --shared-daemon /shared/daemon/dir repoN.git
    

    This command will create repositories and SubGit configuration as the regular configure command, but will also add the shared daemon’s section in the config. It’s also possible to create configuration with the regular configure command, but add the daemon setting later:

    git config -f repo1.git/subgit/config daemon.shared.directory "/shared/daemon/dir"
    ...
    git config -f repoN.git/subgit/config daemon.shared.directory "/shared/daemon/dir"
    
  • the next step is to run the install command for every repository:

    subgit install repo1.git
    subgit install repo2.git
    subgit install repo3.git
    ...
    subgit install repoN.git
    

    with the shared daemon configuration this command will not start the daemon immediately, it will rather prepare the repository for the shared daemon.

  • after everything is prepared, the daemon can be started:

    subgit daemon start /shared/daemon/dir
    

    This command starts the daemon and it will then run all the actual SubGit operations. If needed, it can be stopped by the ’daemon stop command:

    subgit daemon stop /shared/daemon/dir
1 Like

In addition regarding this issue: I have tested versions 3.3.13 and 3.3.14 on Debian Linux and haven’t managed to reproduce the issue, SubGit commands work well even after the repository registration. The subgit register command being invoked on behalf of root (sudo/su) indeed creates a couple of file owned by root, but not in the Git’s objects directory, those are actually the registration process log (subgit-register--.zip) and subgit.key file in the REPO/subgit directory. In fact, this command does not perform any Git operations and thus does not affect Git objects at all, so I believe, those permissions on Git objects in the repository must have been set in some other way – by another process running on behalf of root, for example.

1 Like

Thanks, Ildar; Not able to repro under controlled circumstances now so I guess it must have been a coincidence of timing.

The shared daemon details are super helpful, are they supposed to be in the documentation? Am I having a search-fu fail week, too? :)

I see that it writes some config to the shared daemon directory, is there documentation on how I can convert my existing, running repos to shared daemon?

function convert-to-shared {
  # convert-to-shared <repository> <shared daemon path>
  local repos=$1 ; shift
  local shared=$1 ; shift

  echo >>$repos/subgit/config "[daemon \"shared\"]"
  echo >>$repos/subgit/config "    pidFile = $shared/daemon.pid"

  ?

  git config -f "$repos/subgit/config" daemon.shared.directory "$shared"
}

@ildar.khusainov per the above - I’ve modified the configs of the repositories to add the shared pidfile, which did not get seem to get created when I did this.

Once I managed to get it started, it sits spamming the log with complaints about the non-shared daemon.pid file not existing, and then deletes it just to make sure:

[2022-05-09 23:47:04.973][shared-daemon][30] About to release lock: Lock [file=/var/opt/gitlab/git-data/repositories/@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git/subgit/daemon.lock; memory=java.util.concurrent.locks.ReentrantLock@7a3bae57[Locked by thread Thread-11]; fs=sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]]
[2022-05-09 23:47:04.974][shared-daemon][30] Trying to release file lock on '/var/opt/gitlab/git-data/repositories/@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git/subgit/daemon.lock'.
[2022-05-09 23:47:04.974][shared-daemon][30] Released file lock on '/var/opt/gitlab/git-data/repositories/@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git/subgit/daemon.lock'
[2022-05-09 23:47:04.974][shared-daemon][30] Closed random access file '/var/opt/gitlab/git-data/repositories/@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git/subgit/daemon.lock'
[2022-05-09 23:47:04.974][shared-daemon][30] error while polling repository at '/var/opt/gitlab/git-data/repositories/@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git'
org.tmatesoft.translator.util.f: Failed to launch background translation process: timeout waiting for pid file '/var/opt/gitlab/git-data/repositories/@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git/subgit/daemon.pid'.
    at org.tmatesoft.translator.util.f.b(SourceFile:27)
    at org.tmatesoft.translator.process.r.a(SourceFile:65)
    at org.tmatesoft.translator.daemon.j.b(SourceFile:513)
    at org.tmatesoft.translator.daemon.j.a(SourceFile:379)
    at org.tmatesoft.translator.daemon.j.a(SourceFile:230)
    at org.tmatesoft.translator.daemon.j.a(SourceFile:193)
    at org.tmatesoft.translator.l.k.a(SourceFile:92)
    at org.tmatesoft.translator.l.k.a(SourceFile:53)
    at org.tmatesoft.translator.l.k.call(SourceFile:17)
    at org.tmatesoft.translator.daemon.P$1.call(SourceFile:124)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.tmatesoft.translator.daemon.P.run(SourceFile:77)
[2022-05-09 23:47:04.976][shared-daemon][30] scheduling task to run now
[2022-05-09 23:47:04.976][shared-daemon][30] tasks run complete
[2022-05-09 23:47:04.976][shared-daemon][30] about to be idle for 5481ms.
[2022-05-09 23:47:10.457][shared-daemon][30] about to run 1 tasks
[2022-05-09 23:47:10.458][shared-daemon][30] polling repository 2 of 5
[2022-05-09 23:47:10.458][shared-daemon][30] polling: /var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git
[2022-05-09 23:47:10.466][shared-daemon][30] repository at '/var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git' is idle, will poll
[2022-05-09 23:47:10.466][shared-daemon][30] Obtaining file lock on '/var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git/subgit/daemon.lock'.
[2022-05-09 23:47:10.466][shared-daemon][30] Obtained file lock on '/var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git/subgit/daemon.lock'
[2022-05-09 23:47:10.466][shared-daemon][30] Pid file does not exist: /var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git/subgit/daemon.pid
[2022-05-09 23:47:10.466][shared-daemon][30] Daemon info pid=-1; port=-1; address=; user=null from file '/var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git/subgit/daemon.pid'
[2022-05-09 23:47:10.466][shared-daemon][30] Pid file '/var/opt/gitlab/git-data/repositories/@hashed/19/58/19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git/subgit/daemon.pid' deleted.

the config from one of the repositories contains:

[daemon]
    pidFile = subgit/daemon.pid

    idleTimeout = infinity

    classpath = /usr/share/java/subgit/jansi-1.6.jar:/usr/share/java/subgit/slf4j-nop-1.7.12.jar:/usr/share/java/subgit/unirest-java-1.3.0.jar:/usr/share/java/subgit/javax.ws.rs-api-2.1.jar:/usr/share/java/subgit/jetty-server-9.4.11.v20180605.jar:/usr/share/java/subgit/jetty-servlet-9.4.11.v20180605.jar:/usr/share/java/subgit/jersey-server-2.27.jar:/usr/share/java/subgit/jersey-hk2-2.27.jar:/usr/share/java/subgit/jersey-container-jetty-servlet-2.27.jar:/usr/share/java/subgit/jersey-media-json-jackson-2.27.jar:/usr/share/java/subgit/svnkit-1.10.4.jar:/usr/share/java/subgit/org.eclipse.jgit-5.0.11-sgk.jar:/usr/share/java/subgit/annotations-7.0.3.jar:/usr/share/java/subgit/slf4j-api-1.7.12.jar:/usr/share/java/subgit/httpclient-4.3.jar:/usr/share/java/subgit/httpasyncclient-4.0-beta4.jar:/usr/share/java/subgit/httpmime-4.3.jar:/usr/share/java/subgit/json-20090211.jar:/usr/share/java/subgit/javax.servlet-api-3.1.0.jar:/usr/share/java/subgit/jetty-http-9.4.11.v20180605.jar:/usr/share/java/subgit/jetty-io-9.4.11.v20180605.jar:/usr/share/java/subgit/jetty-security-9.4.11.v20180605.jar:/usr/share/java/subgit/jersey-common-2.27.jar:/usr/share/java/subgit/jersey-client-2.27.jar:/usr/share/java/subgit/jersey-media-jaxb-2.27.jar:/usr/share/java/subgit/javax.annotation-api-1.2.jar:/usr/share/java/subgit/javax.inject-2.5.0-b42.jar:/usr/share/java/subgit/validation-api-1.1.0.Final.jar:/usr/share/java/subgit/hk2-locator-2.5.0-b42.jar:/usr/share/java/subgit/jersey-container-servlet-2.27.jar:/usr/share/java/subgit/jersey-container-jetty-http-2.27.jar:/usr/share/java/subgit/jetty-webapp-9.4.7.v20170914.jar:/usr/share/java/subgit/jersey-entity-filtering-2.27.jar:/usr/share/java/subgit/jackson-annotations-2.8.10.jar:/usr/share/java/subgit/jackson-databind-2.8.10.jar:/usr/share/java/subgit/jackson-module-jaxb-annotations-2.8.10.jar:/usr/share/java/subgit/sequence-library-1.0.4.jar:/usr/share/java/subgit/sqljet-1.1.14.jar:/usr/share/java/subgit/jna-5.6.0.jar:/usr/share/java/subgit/jna-platform-5.6.0.jar:/usr/share/java/subgit/trilead-ssh2-1.0.0-build222.jar:/usr/share/java/subgit/jsch.agentproxy.connector-factory-0.0.7.jar:/usr/share/java/subgit/jsch.agentproxy.svnkit-trilead-ssh2-0.0.7.jar:/usr/share/java/subgit/lz4-java-1.4.1.jar:/usr/share/java/subgit/jsch-0.1.54.jar:/usr/share/java/subgit/JavaEWAH-1.1.6.jar:/usr/share/java/subgit/bcpg-jdk15on-1.62.jar:/usr/share/java/subgit/bcprov-jdk15on-1.62.jar:/usr/share/java/subgit/bcpkix-jdk15on-1.62.jar:/usr/share/java/subgit/httpcore-4.3.jar:/usr/share/java/subgit/commons-logging-1.1.3.jar:/usr/share/java/subgit/commons-codec-1.6.jar:/usr/share/java/subgit/httpcore-nio-4.3-beta2.jar:/usr/share/java/subgit/jetty-util-9.4.11.v20180605.jar:/usr/share/java/subgit/osgi-resource-locator-1.0.1.jar:/usr/share/java/subgit/aopalliance-repackaged-2.5.0-b42.jar:/usr/share/java/subgit/hk2-api-2.5.0-b42.jar:/usr/share/java/subgit/hk2-utils-2.5.0-b42.jar:/usr/share/java/subgit/javassist-3.22.0-CR2.jar:/usr/share/java/subgit/jersey-container-servlet-core-2.27.jar:/usr/share/java/subgit/jetty-continuation-9.4.7.v20170914.jar:/usr/share/java/subgit/jetty-xml-9.4.7.v20170914.jar:/usr/share/java/subgit/jackson-core-2.8.10.jar:/usr/share/java/subgit/antlr-runtime-3.4.jar:/usr/share/java/subgit/jsch.agentproxy.core-0.0.7.jar:/usr/share/java/subgit/jsch.agentproxy.usocket-jna-0.0.7.jar:/usr/share/java/subgit/jsch.agentproxy.usocket-nc-0.0.7.jar:/usr/share/java/subgit/jsch.agentproxy.sshagent-0.0.7.jar:/usr/share/java/subgit/jsch.agentproxy.pageant-0.0.7.jar:/usr/share/java/subgit/javax.inject-1.jar:/usr/share/java/subgit/translator-3.3.13.jar:/usr/share/java/subgit/svngitkit-2.3.4-snapshot20220214112700.jar


[hooks]
    directory = custom_hooks

[daemon "shared"]
    directory = /var/opt/gitlab/git-data/subgit/daemon

which is the same content as “subgit configure” produces if I run it for the same svn url in a different git repository.

Hi Oliver,

it looks like the shared daemon topic is not covered well enough in our documentation, thank you for pointing at that, we will fix it soon.

Configuring a running mirror to use shared daemon in fact as simple as configuring a new mirror with a shared daemon, the only needed thing is to add the daemon "shared" section and the shared daemon directory; the only difference is that the repository-specific daemon must be stopped prior to the reconfiguration, so the steps for a running mirror would be:

  • stop the repository-specific daemon:

    subgit shutdown REPO
    
  • reconfigure the repository to use shared daemon:

    git config -f REPO/subgit/config daemon.shared.directory "/shared/daemon/dir"
    
  • apply the settings in the repository:

    subgit install REPO
    
  • finally, start the shared daemon after all the repositories are configured:

     subgit daemon start /shared/daemon/dir
    

There is no need to change the daemon.pidFile setting, it’s enough to set the shared daemon directory.