more git-subtrac

This commit is contained in:
Motiejus Jakštys 2022-04-26 05:09:10 +03:00
parent 1c256c77d3
commit 10eaf5ff23

View File

@ -16,18 +16,19 @@ Adding dependencies
All of the programming languages I've used professionally whose name does not All of the programming languages I've used professionally whose name does not
start with "c"[^1] have package managers[^2], which make "dependency start with "c"[^1] have package managers[^2], which make "dependency
management" easy. These package managers will, as part of the project's build management" easy. These package managers will, as part of the project's build
process, download and build the dependencies, making adding and using process, download and build the dependencies, which makes adding and using
third-party dependencies easy. third-party dependencies easy.
Because C/C++ still does not have a universal package manager, not adding Because C/C++ still does not have a universal package manager, not adding
external dependencies to C/C++ is the path of least resistance. Instead, it is external dependencies to C/C++ is the path of least resistance; instead, one
common to rely on libraries already installed in the system. Because of this relies on libraries already installed in the system. Therefore, there is a
cultural difference, there is a plethora of dependency managers that will plethora of dependency managers that will discover, but not install
discover, but not install dependencies: autotools, cmake, pkg-config and dependencies: autotools, cmake, pkg-config and others. As a result, C/C++
others. As a result, C/C++ projects I've been involved usually had 0-5 projects I've been involved usually had 0-5 non-system dependencies, whereas
non-system dependencies, whereas non-C/C++ projects -- tens, hundreds or non-C/C++ projects -- tens, hundreds or thousands[^3]. Having many system
thousands[^3]. Having many system dependencies is painful for user experience, dependencies is painful for *every user* of the package (because they have to
so (the good) C/C++ projects also avoid having too many of them. make sure the libraries, and their correct versions, are installed), so C/C++
projects avoid having too many of them.
Not doing things that are easy to do requires discipline: brushing teeth, Not doing things that are easy to do requires discipline: brushing teeth,
limiting candy intake, not adding dependencies all over the place. If it is limiting candy intake, not adding dependencies all over the place. If it is
@ -52,19 +53,30 @@ long-term maintenance costs.
The costs of just having dependencies are huge. I haven't done a survey and The costs of just having dependencies are huge. I haven't done a survey and
have only my experience to base this on (read: "many anecdotes of me failing to have only my experience to base this on (read: "many anecdotes of me failing to
build stuff I wrote a decade ago"). But it is bad enough that I have a build stuff I wrote a decade ago"). But it is bad enough that I have a
dependency checklist and am prepared to do grunt work to avoid or strip it. dependency checklist and am prepared to do the grunt work to save my future
Here is my checklist: self. Here is it:
- Obvious: does it work at all? 1. Does the dependency do what I want, does it work at all?
- How easy is it to build, run and run it's tests? 2. Is it well written? API surface, documentation, tests, error handling, error
- Is it well written? API surface, documentation, tests, error handling, error signaling, logging, metrics, memory usage (if applicable).
signaling, logging, metrics (if applicable), etc. 3. How easy is it to build, run and run it's tests? Related: can it be used
- It's system dependencies. outside the default package manager?
- It's transitive dependencies. 4. It's system dependencies.
5. It's transitive dependencies.
If a dependency is well written, but has more transitive dependencies than I Assuming a "programming-language-specific package manager that does what it's
need and there is no good alternative, I will fork it and remove unnecessary advertised to do", the path of least resistance, when it comes to this
code and dependencies. My recent example is checklist, is doing (1), and perhaps (2). Why bother with transitive
dependencies or it's build complexity, if the package manager will take care of
it all anyway?
Except it will only when you are adding it. Package manager will not help you
when the dependency disappears, it's API changes, it stops doing what it has
advertised and many other [problems][crash-of-leftpad].
I am trying to do all 5. If a dependency is well written, but has more
transitive dependencies than I need and there is no good alternative, I will
fork and trim it. My recent example is
[sql-migrate](https://github.com/motiejus/sql-migrate). [sql-migrate](https://github.com/motiejus/sql-migrate).
To sum up, the "modern" languages optimize for initial development experience, To sum up, the "modern" languages optimize for initial development experience,
@ -72,29 +84,46 @@ not maintenance. And as [Corbet says][linux-rust]. "We can't understand why
Kids These Days just don't want to live that way". Kids want to build, John, Kids These Days just don't want to live that way". Kids want to build, John,
not maintain. A 4-letter Danish corporation made a fortune by selling toys that not maintain. A 4-letter Danish corporation made a fortune by selling toys that
do not need to be maintained: they are designed to be disassembled and built do not need to be maintained: they are designed to be disassembled and built
anew. It is very hard to change the guts of an existing structure without anew. We are still kids. Growing up requires discipline, which is very hard,
rebuilding it. when candy is cheap and package managers (and disks and network, which make all
of it possible) are as good as they are today.
If I may combine Corbet's views with mine: if we understand and audit our If I may combine Corbet's views with mine: if we understand and audit our
dependencies (and transitive ones), we will have less dependencies and a more dependencies (all of them, including transitive ones), we will have less
maintainable system. Win-win. dependencies and a more maintainable system. Win-win.
Which brings us to... Which brings us to...
Transitive dependencies and git-subtrac git-subtrac
--------------------------------------- -----------
[`git-subtrac`][git-subtrac] manages our git dependencies (in our git
repository) just like "classic" git submodules, but all refs of the
dependencies stay in the same repository. Wait, stop here. Repeat after me: _it
is git submodules, but all refs stay in the same repository_. I also call it
"good vendoring". Since all the deps are in our repo, no external force can
make our dependency unavailable, change without notice. And it will keep the
size of the repository in check, because it's all there when you pull it.
Because `git-subtrac` is a vendoring tool, not a package manager, it only
vendors, but does not help building packages. Therefore, with `git-subtrac` it
is harder to add and "make work" (build, test, add transitive deps) a
dependency than with a language-specific package manager. Oh, what about the
transitive dependencies?
[`git-subtrac`][git-subtrac] does not deal with transitive dependencies. At [`git-subtrac`][git-subtrac] does not deal with transitive dependencies. At
least not directly. Or I am not aware of it. Ok, I haven't tried. least not directly. Or I am not aware of it. Ok, I haven't tried.
If we audit and thus understand our dependencies, we will be able to add If we audit and thus understand our dependencies, we will be able to add the
transitive ones to our project even without support of git-subtrac. So perhaps transitive ones. So perhaps git-subtrac shouldn't care?
git-subtrac shouldn't care?
I use [`git-subtrac`][git-subtrac] for some of my projects, and am not very What about Zig?
enthusiastic about Zig getting it's own package manager (can we all use ---------------
git-subtrac and be done with it?). A few weeks ago in a park in Milan my
conversation with [Andrew Kelley](https://andrewkelley.me/) was something like: Zig will have a package manager ([ziglang/zig#943][943]). I am not not very
enthusiastic about it; can we all use git-subtrac and be done with it?. A few
weeks ago in a park in Milan my conversation with [Andrew
Kelley](https://andrewkelley.me/) was something like:
- me: "git-subtrac yadda yadda yadda submodules but better yadda yadda yadda". - me: "git-subtrac yadda yadda yadda submodules but better yadda yadda yadda".
- Andrew: "if I clone a repository that uses it with no extra parameters, will - Andrew: "if I clone a repository that uses it with no extra parameters, will
@ -106,26 +135,15 @@ conversation with [Andrew Kelley](https://andrewkelley.me/) was something like:
Uh, I agree. People have not grown muscle memory to clone repositories with Uh, I agree. People have not grown muscle memory to clone repositories with
`--recursive` flag and never will, so it's impossible to adopt git-subtrac `--recursive` flag and never will, so it's impossible to adopt git-subtrac
beyond well-controlled silos. Which is why we will have a beyond well-controlled silos. Which is why we will have a
yet-another-programming-language-specific-package-manager, this time for zig. yet-another-programming-language-specific-package-manager. Or at least my
Or at least my argument for using git-subtrac stops right there. argument for using and advertising `git-subtrac` (and saving a lot of time for
Zig folks, and a lot of inevitable misery for it's users) stops right there.
Why git-subtrac?
----------------
[`git-subtrac`][git-subtrac] is like "classic" git submodules, but all refs of
the dependencies stay in the same repository. Wait, stop here. Repeat after me:
_it is git submodules, but all refs stay in the same repository_. I also call
it "good vendoring". Since all the deps are in our repo, no external force can
make our dependency unavailable.
It is, howerver, harder to *add* a dependency with submodules than with, say,
`go get <dependency>`. Let's talk about adding dependencies.
Conclusion Conclusion
---------- ----------
Can git checkout local submodules when they are in the same repository, so our Can git check out submodules when they are in the same repository, so our
conversation of reconsidering (or not having) a zig package manager doesn't conversation of reconsidering (or not having) a Zig package manager doesn't
stop after 5 seconds? stop after 5 seconds?
[^1]: Alphabetically: Erlang, Go, Java, Javascript, PHP, Perl, Python. [^1]: Alphabetically: Erlang, Go, Java, Javascript, PHP, Perl, Python.
@ -137,3 +155,5 @@ stop after 5 seconds?
[git-subtrac]: https://github.com/apenwarr/git-subtrac/ [git-subtrac]: https://github.com/apenwarr/git-subtrac/
[linux-rust]: https://lwn.net/SubscriberLink/889924/a733d6630e3b5115/ [linux-rust]: https://lwn.net/SubscriberLink/889924/a733d6630e3b5115/
[crash-of-leftpad]: https://drewdevault.com/2021/11/16/Cash-for-leftpad.html
[943]: https://github.com/ziglang/zig/issues/943