How to work on 2 libraries at once

So I’ve got a a public library on Github. I’ve also created a repository for my own private stuff. For that I’ve created a bare repository on my local NUC server sitting on my home network connecting over SSH. That doesn’t really matter to the question. My public repository has a Util module, I not only want to use this code for my private stuff, but modify and improve it at the same time. Committing and pushing the changes to the two repositories I want to keep completely separate.

So I’m wondering how best to handle this. I imagine that wanting to work on 2 libraries or a library and an application at the same time must be quite common. As I’m writing I’m thinking that maybe the best way is just to put a soft directory link to the local public library source code in the local private project folder on my desktop and laptop. Put the link into the gitignore, but include the linked directory(ies) in Sbt and Mill files for the private project as if it were one combined project.

Your setup is probably somewhat uncommon as one library is private while the other is public.

There’s no inherent requirement to couple commiting with publishing unless of course publishing is done on separate machine than commiting. You can publish snapshots to your local repository at any time. You don’t even have to use any version control system when doing that. If you want to see changes immediately (without the publishing step) then you have to couple your private project with your public project. I think it should be relatively easy in SBT, like:

// refer to directory under different VCS root
lazy val publicLib = project.in(file("../publicLib"))
// refer to code in current VCS root
lazy val privateApp = project.in(file("."))
  .dependsOn(publicLib)

However, there’s a risk of race conditions if you run two SBT instances simultaneously, one in publicLib and one in privateApp.

Actually, I don’t know about that – we have a bunch of that at work: probably a hundred libraries total, of which maybe half a dozen (stuff that isn’t meaningfully proprietary, and seems to be of general interest) are public. We maintain separate organizations for the public vs. private sides.

That said, we don’t maintain any sort of path-connection between them: all of our libraries, inside or outside, get published and depended upon entirely conventionally. Indeed, even for Querki I always do it that way, and it’s what I would recommend. Don’t do soft directory links or anything like that: keep the libraries truly separate, use normal sbt dependencies, and use publishLocal to keep them in sync during development.

1 Like

Try this instead:

// refer to directory under different VCS root
lazy val publicLib = RootProject(file("../publicLib")
// refer to code in current VCS root
lazy val privateApp = project.in(file("."))
  .dependsOn(publicLib)

The difference is that:

  1. in the former you’re declaring, in the build of privateApp, a project whose base directory is at ../publicLib, and then depending on it;
  2. in the latter you’re declaring that there is a build with a root project, at ../publicLib and you want your local privateApp project to depend on the project in that build.

This means that you’ll load privateApp's build, distinct to ThisBuild (which is publicApp’s build), so things should work better.

1 Like