Svnman
Svnman (pronounced ess-vee-en-man) is the ProgClub Subversion project administration software. That's the software that manages creation, maintenance, and release of Subversion projects. Svnman also supports recursive svn:externals pinning with its freeze and unfreeze features. For other projects see projects.
Status
We use semantic versioning. Latest production version: 1.0. Latest development version: 1.0.
See tasks for work that still needs to be done.
Motivation
Why this software? Basically to help with project administration, particularly around versioning of artefacts.
Example usage
You can follow this walk through on your own computer. To get set up:
$ sudo apt install php-cli subversion
Then get a copy of the code:
$ svn co https://www.progclub.org/svn/pcrepo/svnman/trunk /tmp/svnman
And create an alias for access:
$ alias svnman='/usr/bin/env php /tmp/svnman/bin/svnman.php'
Then create a demo repository for testing purposes:
$ svnadmin create /tmp/demorepo
You can then configure a repository alias with the config subcommand. A repository alias allows you to refer to repository location, working base directory, and other settings, with an alias that has those details associated with it. For example to configure a 'demorepo' alias for our demo Subversion repository and working base directory:
jj5@tact:/tmp$ svnman config \
--alias demorepo \
--location file:///tmp/demorepo \
--working-base /tmp
Note that the working base directory is the parent directory of our working copies. So we're just gonna put our working copies in /tmp
for this demo.
Now you can create a new project named 'svnman-demo' in the 'demorepo' repository like this:
jj5@tact:/tmp$ svnman create \
--project-name svnman-demo \
--repo demorepo
The output will be something like this:
/tmp/svnman-demo-0.1
which indicates that your new project has been checked out into /tmp/svnman-demo-0.1
, so go there:
jj5@tact:/tmp$ cd /tmp/svnman-demo-0.1
You can edit bin/dev/gen.sh
to configure code generation steps done before each checkin. We'll ignore code generation for this demo.
Let's create a test program like this:
jj5@tact:/tmp/svnman-demo-0.1$echo $'#!/usr/bin/env php\n<?php echo "hello, world.\n";' > bin/hello.php
jj5@tact:/tmp/svnman-demo-0.1$chmod +x bin/hello.php
jj5@tact:/tmp/svnman-demo-0.1$svn add bin/hello.php
You can then commit with svnman. Committing with svnman ensures that code maintenance is run prior to checkin. Maintenance involves an optional code generation step and then the increment of the PATCH version number. By default the version numbers are in inc/version.php
. Run the following commands to see the SVNMAN_DEMO_VERSION_PATCH version incremented from 1 to 3:
jj5@tact:/tmp/svnman-demo-0.1$cat inc/version.php
jj5@tact:/tmp/svnman-demo-0.1$svnman commit -m 'Commit messages are optional.'
jj5@tact:/tmp/svnman-demo-0.1$cat inc/version.php
If you're happy with v0.1 you can release it:
jj5@tact:/tmp/svnman-demo-0.1$ svnman release
The release process created the following branches/tags in our Subversion repository:
latest...: file:///tmp/demorepo/svnman-demo/tags/latest/0.1 major....: file:///tmp/demorepo/svnman-demo/tags/major/0 minor....: file:///tmp/demorepo/svnman-demo/tags/minor/0/1 release..: file:///tmp/demorepo/svnman-demo/tags/release/0/1/4 trunk....: file:///tmp/demorepo/svnman-demo/trunk
You can use svn ls
to inspect, e.g.:
jj5@tact:/tmp/svnman-demo-0.1$ svn ls file:///tmp/demorepo/svnman-demo/trunk
You can see the version config file for your release here:
jj5@tact:/tmp/svnman-demo-0.1$ svn cat file:///tmp/demorepo/svnman-demo/trunk/inc/version.php
Note that for your production release in trunk
the SVNMAN_DEMO_VERSION_PATCH version is 4. Your development branch is at 5, see:
jj5@tact:/tmp/svnman-demo-0.1$ cat inc/version.php
Maintaining that PATCH version number — and making sure it is regularly and consistently updated — is perhaps the main job of svnman. See the Versioning section for details, but basically an even PATCH version is for a PROD (for "production") build, and an odd PATCH version is for a DEV (for "development") build. The release process makes sure the PATCH version number is properly incremented during each stage of a release.
So now that v0.1 is released, it's time to get ready for development of v0.2 with bump-minor. The bump-minor subcommand will increment the MINOR version number from 1 to 2:
jj5@tact:/tmp/svnman-demo-0.1$ svnman bump-minor
The output will be something like this:
/tmp/svnman-demo-0.2
which indicates that your new project version has been checked out into /tmp/svnman-demo-0.2
, so go there:
jj5@tact:/tmp/svnman-demo-0.1$ cd /tmp/svnman-demo-0.2
In order to test freezing/unfreezing of svn:externals when we run our release (below) we need to set up an extra project we can use as a library:
jj5@tact:/tmp/svnman-demo-0.2$ svnman create \
--project-name svnman-demo-lib \
--repo demorepo
Now for v0.2 let's include our library project as an external project:
jj5@tact:/tmp/svnman-demo-0.2$ svn propset svn:externals \
"svnman-demo-lib file:///tmp/demorepo/svnman-demo-lib/branches/0.1" ext
And commit our changes:
jj5@tact:/tmp/svnman-demo-0.2$ svnman commit
Now if you do an `svn up` you will get a copy of svnman-demo-lib in the ext
dir:
jj5@tact:/tmp/svnman-demo-0.2$svn up
jj5@tact:/tmp/svnman-demo-0.2$ls ext/
Now let's change our program a little bit for v0.2:
jj5@tact:/tmp/svnman-demo-0.2$ echo $'#!/usr/bin/env php\n<?php echo "hello from v0.2!\n";' > bin/hello.php
And commit our changes:
jj5@tact:/tmp/svnman-demo-0.2$ svnman commit
So v0.2 looks fairly good, let's release it:
jj5@tact:/tmp/svnman-demo-0.2$ svnman release
As before the release process created a bunch of branches/tags in our Subversion repository:
latest...: file:///tmp/demorepo/svnman-demo/tags/latest/0.2 major....: file:///tmp/demorepo/svnman-demo/tags/major/0 minor....: file:///tmp/demorepo/svnman-demo/tags/minor/0/2 release..: file:///tmp/demorepo/svnman-demo/tags/release/0/2/12 trunk....: file:///tmp/demorepo/svnman-demo/trunk
So we're done with v0.2, let's get ready for our v1.0 release with bump-major. The bump-major command will increment the MAJOR version number from 0 to 1:
jj5@tact:/tmp/svnman-demo-0.2$ svnman bump-major
The output will be something like this:
/tmp/svnman-demo-1.0
which indicates that your new project version has been checked out into /tmp/svnman-demo-1.0
, so go there:
jj5@tact:/tmp/svnman-demo-0.2$ cd /tmp/svnman-demo-1.0
Again we can modify our program for v1.0:
jj5@tact:/tmp/svnman-demo-1.0$ echo $'#!/usr/bin/env php\n<?php echo "hello from v1.0!\n";' > bin/hello.php
And commit:
jj5@tact:/tmp/svnman-demo-1.0$ svnman commit
And release:
jj5@tact:/tmp/svnman-demo-1.0$ svnman release
And now v1.0 is in production:
latest...: file:///tmp/demorepo/svnman-demo/tags/latest/1.0 major....: file:///tmp/demorepo/svnman-demo/tags/major/1 minor....: file:///tmp/demorepo/svnman-demo/tags/minor/1/0 release..: file:///tmp/demorepo/svnman-demo/tags/release/1/0/18 trunk....: file:///tmp/demorepo/svnman-demo/trunk
You can look at the version file to see the MAJOR.MINOR.PATCH version numbers which are now at v1.0.19:
jj5@tact:/tmp/svnman-demo-1.0$ cat inc/version.php
Example output:
<?php define( 'SVNMAN_DEMO_VERSION_MAJOR', 1 ); define( 'SVNMAN_DEMO_VERSION_MINOR', 0 ); define( 'SVNMAN_DEMO_VERSION_PATCH', 19 ); define( 'SVNMAN_DEMO_NAME', 'svnman-demo' ); define( 'SVNMAN_DEMO_CODE', 'svnman-demo' ); define( 'SVNMAN_SVN_DATE', '$Date: 2020-02-28 13:29:00 +1100 (Fri, 28 Feb 2020) $' ); define( 'SVNMAN_SVN_REVISION', '$Revision: 6131 $' ); define( 'SVNMAN_SVN_AUTHOR', '$Author: jj5 $' );
And have a look at the svn:externals on the release tag for our v1.0 release:
jj5@tact:/tmp/svnman-demo-1.0$ svn propget svn:externals \
file:///tmp/demorepo/svnman-demo/tags/latest/1.0/ext
The output will be something like this:
svnman-demo-lib -r35 file:///tmp/demorepo/svnman-demo-lib/branches/0.1
Compare that with the development version from the 1.0 version branch:
jj5@tact:/tmp/svnman-demo-1.0$ svn propget svn:externals \
file:///tmp/demorepo/svnman-demo/branches/1.0/ext
The output will be something like this:
svnman-demo-lib file:///tmp/demorepo/svnman-demo-lib/branches/0.1
Notice that for the tagged release the svn:externals have been "frozen" on revision 6124, whereas for the development version on the version branch the externals definition is not pinned to a specific revision but is tracking HEAD. That's a consequence of the freeze and unfreeze processes which happen automatically before and after a release. Freezing and unfreezing of svn:externals before creating release tags is another main reason for using svnman.
You can clean up after yourself like this:
$cd ~ && rm -rf /tmp/demorepo /tmp/svnman*
$unalias svnman
If you like what you see please see the Installation Guide for help with configuring svnman in production.
Administration
Contributors
Members who have contributed to this project. Newest on top.
All contributors have agreed to the terms of the Contributor License Agreement. This excludes any upstream contributors who tend to have different administrative frameworks.
Copyright
Copyright © 2020, Contributors.
License
Licensed under the MIT license.
Components
Libraries, tools, services or media from third parties used under license:
Resources
Downloads
There are presently no tarballs. Running an `svn checkout` against the ProgClub Subversion repository is the recommended way to install this software. See installation for more information.
Source code
The source code can be browsed online:
The most interesting code is here:
The latest stable (read-only) released version of the code is available from Subversion here:
Or if you want the latest version for development purposes:
Note that our software development is done on the version branch, not on trunk. We use trunk to track the latest stable release.
Links
- Version Control with Subversion (svnbook)
Specifications
Versioning
The versioning article goes into more detail, but basically the version numbers supported by svnman are in the format MAJOR.MINOR.PATCH. Note that this versioning standard is used by both the svnman software itself and also any projects which use svnman as their project administration tool. This versioning standard is the only versioning standard supported by svnman at the present time. Note that there can be multiple MAJOR.MINOR releases whereas a specific MAJOR.MINOR.PATCH release is unique. This means that you can continue issuing patches (such as security updates) to particular MAJOR.MINOR versions and releasing them. If you need a new MAJOR.MINOR version (say for your next prospective production release) then see the bump-minor subcommand for help with that. If you're getting ready for a new MAJOR version (which you should definitely consider if you're planning to introduce breaking changes) then see bump-major. The versioning specification has support for extra version info, but that is not relevant to svnman, and svnman can be used with or without that extra information.
Version component | Description | Details |
---|---|---|
MAJOR | major version number | incremented for breaking changes, except for version zero which may be unstable |
MINOR | minor version number | incremented for non-breaking changes for new supported versions |
PATCH | patch version number | incremented prior to every commit (and release); the PATCH is odd for DEV builds and even for PROD builds; not all PATCH versions get released |
Repository layout
This software presumes that the Subversion project has the typical base directories:
- trunk
- branches
- tags
However, we don't use 'trunk' for development. Instead development happens in MAJOR.MINOR version branches.
When a version branch is released by svnman 'trunk' can optionally be updated. Within 'tags' the latest MAJOR.MINOR versions are maintained under 'tags/latest/MAJOR.MINOR' and releases are tagged under 'tags/release/MAJOR/MINOR/PATCH'.
Version branches
Version branches are project branches (under the "branches" directory in the Subversion repository) with a directory name in the format MAJOR.MINOR. It's possible to have other sorts of branches (svnman will ignore those) but the branches that svnman does operate on must be version branches in the valid format.
So version 0.3 is developed in 'branches/0.3' and version 1.0 is developed in 'branches/1.0'.
For example the version branch for v1.0 of the svnman software is:
Builds
Only two types of builds are supported by svnman: DEV and PROD. If you want to cut a BETA or Release Candidate (RC1, RC2, etc.) build, you can do that (see the versioning article for help on this topic), but it's best to use a DEV build for those, saving PROD for real live actual supported versions. When you run a release with the `svnman release` subcommand a PROD build is configured for release. After the production release the project is reconfigured as the next DEV build. So PROD builds only exist during a release, and before and after a release the project is for a DEV build. In this way all releases are releases to PROD, that's what 'release' means.
DEV
A 'DEV' (for "development") build is for a programmer or tester for testing and development purposes. You can use a DEV build in production if you want, but it might have known errors, change rapidly, or otherwise be unsupported. You can tell DEV builds by their odd PATCH version number (PATCH % 2 == 1). If you track the version branch you will typically see a DEV build, except for temporarily during an `svnman release`.
PROD
A 'PROD' (for "production") build is created by a project administrator (using the `svnman release` subcommand) when testing of the version branch is complete. You can tell PROD builds by their even PATCH version number (PATCH % 2 == 0). During a release PROD builds get tagged with their MAJOR.MINOR version number under 'tags/latest/' and also with their MAJOR/MINOR/PATCH version number under 'tags/release/'. Usually when the latest version branch is released to PROD we update 'trunk' to point at it. In this way 'trunk' usually tracks the latest stable production version, which might be different to what you're used to. If you track 'trunk' or 'tags' you should only ever see PROD builds, as DEV builds only happen on the version branch.
Functional specification
The functional specification describes what the project does.
The software provides a system command called `svnman` which has various subcommands for administering projects in a Subversion repository. For details see the command-line interface.
Technical specification
The technical specification describes how the project works.
The software is written in PHP (tested on version 7.2) and shells out to the `svn` command-line utility (tested on version 1.9.7).
Configuration data is kept in JSON format in $HOME/.config/svnman/config.json
. Use the `svnman config` subcommand to specify configuration data via the command-line.
Command-line interface
general usage: svnman SUBCOMMAND [ARG...] [DIR...] A Subversion project management tool. Type `svnman help <subcommand>` for help on a specific subcommand. Type `svnman version` to see the program version. Type `svnman errors` to see information about possible program errors.
- find us on the web: https://www.progclub.org/wiki/svnman
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
SUBCOMMAND
Available subcommands:
- config
- create
- maint
- commit (or ci)
- freeze
- unfreeze (or thaw)
- release
- bump-minor
- bump-major
- browse
- gen-doc
- gen-vars
- fix-version
Arguments
Available arguments:
--quiet
-q [--quiet] .........: suppress error/warning/debug output
--debug
--debug ..............: output extra info for debugging
--repo
--repo ALIAS|URL .....: Subversion repository to operate on; note that if you nominate an ALIAS then other options (such as --working-base etc) can be inferred from your config file
--alias
--alias ALIAS ........: name of a repository alias; see the config subcommand for more information
--location
--location URL .......: location of the repository
--working-base
--working-base DIR ...: parent directory of the working copy; if unspecified it is loaded from the config file (if possible); if unspecified and not configured then checkout options that depend on this setting will be skipped.
--working-copy
--working-copy DIR ...: directory containing the working copy; if unspecified the working copy will go under --working-base in a directory calculated using the --project-name and the MAJOR.MINOR version such as e.g. svnman-1.0
--viewvc
--viewvc URL .........: ViewVC URL for the repository; see the browse subcommand for notes on how this setting is used
--project-name
--project-name NAME ..: name of the project; this will be used in the repository as the project name and also as part of the working copy path (if --working-copy is unspecified)
--project-code
--project-code CODE ..: project code (lowercase); generated from --project-name if unspecified
--project-const
--project-const CONST : project const (uppercase); generated from --project-code if unspecified
--checkout
--checkout ...........: checkout into working copy [default]
--no-checkout
--no-checkout ........: don't checkout into working copy
--trunk
--trunk ..............: trunk is updated
--no-trunk
--no-trunk ...........: trunk is not updated
--auto-trunk
--auto-trunk .........: trunk updated if project is on latest branch [default]
--phpbom
--phpbom .............: configure svn:externals on ext DIR for PHPBOM library
--no-phpbom
--no-phpbom ..........: don't configure the PHPBOM library [default]
--message
-m [--message] STRING : `svn commit` message; the commit message is always optional; we recommend not using it
Argument formats
ARG
An argument is a name prefixed with two dashes, optionally followed by whitespace and a value, depending on the argument. For example:
--no-trunk
Or:
--repo pcrepo
The special arguemnt '--' indicates that all subsequent command-line values are to be treaded as DIRs not as ARGs.
Note that some arguments also support a shorter version, which is usually a dash followed by a single letter. For example --message can be abbreviated as -m.
DIR
A PATH to a directory in the local file system. Absolute and relative paths are supported for input, but if directory paths are stored (such as with working base directories in repository aliases) the absolute paths are computed and stored at the time of configuration not at time of later use.
Note that if no DIRs are provided the current working directory is processed.
PATH
A location in the local file system. Absolute or relative paths are supported. A path can be to a standard file, directory, symlink, etc. Generally if a directory is required we explicitly document it as a DIR. If your PATH is to the wrong type of file per your SUBCOMMAND/ARG then you can expect to see an error as a result.
URL
A Uniform Resource Locator, typically with a scheme such as:
- http:
- https:
- file:
- svn:
NAME
Name format:
/^[a-z][a-z0-9\._-]{0,42}[a-z0-9]$/
CODE
Code format:
/^[a-z][a-z0-9-]{0,14}[a-z0-9]$/
CONST
Const format:
/^[A-Z][A-Z0-9_]{0,14}[A-Z0-9]$/
ALIAS
Alias format:
/^[a-z][a-z0-9-]{0,14}[a-z0-9]$/
STRING
String format:
/^[^\x00-\x09\x0b\x0c\x0e-\x1f\x7f]*$/
Subcommands
config
config: usage: svnman config ARG...
Configure an svnman repository alias.
A repository alias associates an alias with a repo location, allowing the repo alias to be used as a shortcut for the repo location in commands which accept a --repo argument. A default working base DIR and a ViewVC URL can also be associated with a repo alias.
Note that the config file is in JSON format in:
$HOME/.config/svnman/config.json
If your alias is not already configured then --location is required. If it is already configured the existing location will be retained if a new location is not nominated. If you want to clear an optional setting you can set it to the empty string ().
Required arguments:
--alias ALIAS ........: name of a repository alias; see the config subcommand for more information
Optional arguments:
--location URL .......: location of the repository --working-base DIR ...: parent directory of the working copy; if unspecified it is loaded from the config file (if possible); if unspecified and not configured then checkout options that depend on this setting will be skipped. --viewvc URL .........: ViewVC URL for the repository; see the browse subcommand for notes on how this setting is used
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
create
create: usage: svnman create ARG...
Create a new project in a Subversion repository.
New projects are created with:
MAJOR version = 0 MINOR version = 1 PATCH version = 1
The odd PATCH version indicates that the initial version is a DEV version.
So basically a new project is just a couple of standard directories in the repository along with an initial version file. Also, if you've included the PHPBOM library, the svn:externals for that will be configured too.
Depending on your command-line options the initial 'branches/0.1' version will be checked out into a working copy for you.
Required arguments:
--project-name NAME ..: name of the project; this will be used in the repository as the project name and also as part of the working copy path (if --working-copy is unspecified) --repo ALIAS|URL .....: Subversion repository to operate on; note that if you nominate an ALIAS then other options (such as --working-base etc) can be inferred from your config file
Optional arguments:
--project-code CODE ..: project code (lowercase); generated from --project-name if unspecified --project-const CONST : project const (uppercase); generated from --project-code if unspecified --working-base DIR ...: parent directory of the working copy; if unspecified it is loaded from the config file (if possible); if unspecified and not configured then checkout options that depend on this setting will be skipped. --working-copy DIR ...: directory containing the working copy; if unspecified the working copy will go under --working-base in a directory calculated using the --project-name and the MAJOR.MINOR version such as e.g. svnman-1.0 --checkout ...........: checkout into working copy [default] --no-checkout ........: don't checkout into working copy --phpbom .............: configure svn:externals on ext DIR for PHPBOM library --no-phpbom ..........: don't configure the PHPBOM library [default]
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
maint
maint: usage: svnman maint [DIR...]
Run maintenance on DIR.
Maintenance includes optional code generation and updating of the PATCH version. You should run this before your commits. You can only run maintenance on DEV builds and this is enforced by this subcommand. If your working copy is for a PROD build (i.e. has an even PATCH version number) then you may need to run `svnman fix-version` to remedy the situation.
For the code generation the file 'bin/dev/gen.sh' is executed, if it exists and is executable.
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
commit
commit: usage: svnman commit|ci [DIR...]
Run maintenance on DIR then commit.
See `svnman help maint` for information concerning the maintenance process. After maintenance (assuming it is successful) an `svn commit` is performed.
Note that if you are running `svn commit` (AKA: `svn ci`) directly then you should make sure you call `svnman maint` to run maintenance *before* an actual commit. If you don't do this the PATCH version number will not be incremented properly. If you absolutely must run `svn commit` directly then make sure you have incremented the PATCH version by two (to an ODD number) in the version file for your project prior to commit. Run `svnman version` if you need to know which file is being used for version info in your current working directory.
Optional arguments:
-m [--message] STRING : `svn commit` message; the commit message is always optional; we recommend not using it
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
freeze
freeze: usage: svnman freeze [DIR...]
Freeze external subprojects in DIR.
Only available for projects that are in branches. When fronzen externals are pinned to the revision which was current at the time of freezing.
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
unfreeze
unfreeze: usage: svnman unfreeze|thaw [DIR...]
Unfreeze external subprojects in DIR.
Only available for projects that are in branches. When unfronzen externals are unpinned from a specific revision.
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
release
release: usage: svnman release [ARG...] [DIR...]
Release a project in DIR.
Prior to release projects are frozen, and after release they are unfrozen. When a release is done the starting version must be a DEV build (with an odd PATCH version number), then during the release the PATCH version number will be incremented to an even version number for the release, and after the release the PATCH version number will be incremented again to a new odd version number for use by the next DEV build.
So the release process is roughly:
- freeze
- bump PATCH to next PROD version
- commit
- create tags
- optionally update trunk
- unfreeze
- bump PATCH to next DEV version
- commit
Optional arguments:
--trunk ..............: trunk is updated --no-trunk ...........: trunk is not updated --auto-trunk .........: trunk updated if project is on latest branch [default]
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
bump-minor
bump-minor: usage: svnman bump-minor [DIR...]
Create a new version branch from DIR, incrementing the MINOR version number.
Note that during a MINOR version bump the PATCH version is preserved. This means that across MAJOR.MINOR versions PATCH version numbers will duplicate and diverge. This is by design. One consequence of this is that the PATCH number indicates, for every MAJOR.MINOR version, pretty much exactly how many commits have been made in that version's entire history.
Note also that the MINOR version number will be updated in both the URL for the branch and in the project version file (so that's in two places).
Optional arguments:
--working-base DIR ...: parent directory of the working copy; if unspecified it is loaded from the config file (if possible); if unspecified and not configured then checkout options that depend on this setting will be skipped. --working-copy DIR ...: directory containing the working copy; if unspecified the working copy will go under --working-base in a directory calculated using the --project-name and the MAJOR.MINOR version such as e.g. svnman-1.0 --checkout ...........: checkout into working copy [default] --no-checkout ........: don't checkout into working copy
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
bump-major
bump-major: usage: svnman bump-major [DIR...]
Create a new version branch from DIR, incrementing the MAJOR version number (and resetting the MINOR version number to zero).
Note that during a MAJOR version bump the PATCH version is preserved. This means that across MAJOR.MINOR versions PATCH version numbers will duplicate and diverge. This is by design. One consequence of this is that the PATCH number indicates, for every MAJOR.MINOR version, pretty much exactly how many commits have been made in that version's entire history.
Note also that the MAJOR version number will be updated in both the URL for the branch and in the project version file (so that's in two places).
Optional arguments:
--working-base DIR ...: parent directory of the working copy; if unspecified it is loaded from the config file (if possible); if unspecified and not configured then checkout options that depend on this setting will be skipped. --working-copy DIR ...: directory containing the working copy; if unspecified the working copy will go under --working-base in a directory calculated using the --project-name and the MAJOR.MINOR version such as e.g. svnman-1.0 --checkout ...........: checkout into working copy [default] --no-checkout ........: don't checkout into working copy
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
browse
browse: usage: svnman browse [DIR...]
Open ViewVC in web browser for project in DIR.
This requires ViewVC to be configured via `svnman config`.
// 2020-02-27 jj5 - NOTE: this functionality hasn't been implemented yet!
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
gen-doc
gen-doc: usage: svnman gen-doc
Generates svnman documentation for use in the project wiki.
You can find said documentation here:
Have a look in the 'bin/dev/gen.sh' script to see how documentation generation is done.
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
gen-vars
gen-vars: usage: svnman gen-vars
Generates shell config containing error constants definitions.
You can `source` the output of this command to configure your environment with error info:
`source <(svnman gen-vars)`
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
fix-version
fix-version: usage: svnman fix-version [DIR...]
If the PATCH version number is left on an even value (perhaps due to a failure during `svnman release`) then this subcommand will bump it to the next odd value, making it a valid development PATCH version number again. If the PATCH version number is already an odd value this subcommand does nothing and fails indicating error.
For more info on our version numbers see:
Global arguments:
-q [--quiet] .........: suppress error/warning/debug output --debug ..............: output extra info for debugging
For help on argument formats see `svnman help`.
Errors
Potential svnman error levels and their meaning:
Error level | Error name | Error text | Hint |
---|---|---|---|
0 | ERR_SUCCESS | program completed successfully. | |
10 | ERR_HELP | help (or version/error info) requested. | |
11 | ERR_PHP_ERROR | PHP error. | please let the maintainer know: John Elliot V <jj5@progclub.org> |
12 | ERR_PHP_EXCEPTION | unhandled exception. | please let the maintainer know: John Elliot V <jj5@progclub.org> |
13 | ERR_PHP_ASSERT | assertion failed. | please let the maintainer know: John Elliot V <jj5@progclub.org> |
14 | ERR_NO_ASSERTIONS | "zend.assertions" are not enabled. | enable "zend.assertions" in php.ini. |
15 | ERR_NOT_IMPLEMENTED | functionality not implemented. | |
16 | ERR_NOT_SUPPORTED | situation not supported. | please let the maintainer know: John Elliot V <jj5@progclub.org> |
17 | ERR_NOT_A_DIRECTORY | not a directory. | |
18 | ERR_NOT_A_DEV_BUILD | not a DEV build. | this is a PROD build. For a DEV build increment the PATCH by 1. Try `svnman fix-version`. |
19 | ERR_INVALID_PATH | invalid path. | |
20 | ERR_INVALID_BRANCH_VERSION | invalid branch version. | make sure VERSION in branches/VERSION is in format MAJOR.MINOR. |
21 | ERR_INVALID_VERSION | version discrepancy. | check the branches/VERSION is same as MAJOR/MINOR from version file. |
22 | ERR_INVALID_VERSION_PART | invalid version part. | |
23 | ERR_INVALID_WORKING_BASE | invalid working base. | |
24 | ERR_INVALID_EXTERNALS | invalid svn:externals. | |
25 | ERR_INVALID_EXTERNALS_DIR | invalid svn:externals directory. | the directory should come first. |
26 | ERR_INVALID_NAME | invalid name. | |
27 | ERR_INVALID_CODE | invalid code. | |
28 | ERR_INVALID_CONST | invalid const. | |
29 | ERR_INVALID_ALIAS | invalid repository alias. | |
30 | ERR_INVALID_STRING | invalid string. | |
31 | ERR_INVALID_VERSION_PATCH | invalid version PATCH. | |
32 | ERR_INVALID_CONFIG | invalid config. | your config file is corrupt, consider deleting it or revise. |
33 | ERR_MISSING_HOME_ENV_VAR | missing $HOME environment variable. | review your shell configuration such as .bashrc. |
34 | ERR_MISSING_ARG_VALUE | missing argument value. | |
35 | ERR_MISSING_ALIAS | missing --alias. | |
36 | ERR_MISSING_LOCATION | missing --location. | |
37 | ERR_MISSING_HOME_DIR | missing $HOME directory. | |
38 | ERR_MISSING_VERSION_FILE | missing version file. | |
39 | ERR_MISSING_VERSION_PART | missing version part. | |
40 | ERR_MISSING_PROJECT_NAME | missing project name. | |
41 | ERR_VERSION_CONFLICT_MAJOR | MAJOR version conflict. | check the branches/VERSION indicates same as MAJOR in version file. |
42 | ERR_VERSION_CONFLICT_MINOR | MINOR version conflict. | check the branches/VERSION indicates same as MINOR in version file. |
43 | ERR_PATCH_VERSION_EVEN | PATCH version is even (PROD). | consider running `svnman fix-version` to resolve. |
44 | ERR_PATCH_VERSION_ODD | PATCH version is odd (DEV). | if PATCH version is odd there's no need to run `svnman fix-version`. |
45 | ERR_EXPECTED_BRANCHES | expected "branches". | |
46 | ERR_MKDIR_FAILED | mkdir failed. | |
47 | ERR_CHDIR_FAILED | chdir failed. | |
48 | ERR_NO_EXTERNALS | no externals. | |
49 | ERR_NOT_WORKING_COPY | not an svn working copy. | |
50 | ERR_CANNOT_MAKE_TEMP_DIR | cannot make temp dir. | |
51 | ERR_CANNOT_MATCH_VERSION_PATCH | cannot match version PATCH. | |
52 | ERR_SVN_MISSING | no executable `svn` command. | |
53 | ERR_SVN_COMMAND_FAILED | svn command failed. | |
54 | ERR_SVN_CANNOT_ACCESS | cannot access svn repository. | |
55 | ERR_SVN_INVALID_INFO | unsupported `svn info` output. | please let the maintainer know: John Elliot V <jj5@progclub.org> |
56 | ERR_SVN_HAS_CHANGES | found uncommitted changes. | |
57 | ERR_SVN_BRANCH_EXISTS | branch already exists. | |
58 | ERR_FILE_WRITE | error writing file. | |
59 | ERR_FILE_CLOSE | error closing file. | |
60 | ERR_FILE_UNLINK | error unlinking file. | |
61 | ERR_FILE_MISSING | file missing. | |
62 | ERR_CODE_GEN_NOT_EXECUTABLE | code gen script not executable. | you may need to run `chmod +x` on your code gen script. |
63 | ERR_CODE_GEN_FAILED | code generation failed. | |
64 | ERR_CONFIG_WRITE_FAILED | error writing config file. | |
65 | ERR_UNSUPPORTED_FILE_TYPE | unsupported file type. | |
66 | ERR_URL_TRUNK | URL is a trunk branch. | make sure your project is in "branches/MAJOR.MINOR". |
67 | ERR_URL_TAGS | URL is a tags branch. | make sure your project is in "branches/MAJOR.MINOR". |
68 | ERR_URL_NOT_A_VERSION_BRANCH | URL is not a version branch. | make sure your project is in "branches/MAJOR.MINOR". |
Miscellanea
Subversion
The svnman software makes use of the Subversion command-line interface. If Subversion is not installed then svnman won't work!
svn:externals
The Subversion software allows for named properties to be set on files/directories that are under source control. Some of these properties are special Subversion properties which have special meaning. One such property is the 'svn:externals' property. The 'svn:externals' property allows for external Subversion projects to be configured as dependencies of the current project. This allows for your Subversion project to use other Subversion projects which will get loaded from their sources automatically during svn checkout or update. Our svnman software has special support for svn:externals via our freeze and unfreeze processes (both of which happen automatically during a release).
The svn:externals specification format allows for the optional specification of a repository revision number to 'pin' an external project at a specific revision. When pinned an svn:externals definition will always checkout the same version of the external dependency. When unpinned the HEAD revision of the external dependency will be used (during checkout and update etc).
As an example you can see an svn:externals definition on the PHPBOM library:
Look down the bottom of the page for the above URL and you will see the 'svn:externals' property and its configuration. This configuration causes the 'bugslist' software to be included as an external project for the 'phpbom' software. The svn:externals definition from the above is on the version branch and therefore has no revision number specified and thus tracks HEAD. However a released version of PHPBOM will be pinned, see for example:
Look down the bottom of the page for the above URL and you will see the 'svn:externals' property has been configured to point to a specific revision number of -r6190.
All in all svn:externals is a very important Subversion feature which enables much of the functionality of svnman.
ViewVC
The ViewVC software can be used for browsing a Subversion repository via the web. We intend to support ViewVC integration, but, ah, that isn't done yet...
PHP
The svnman software is written mostly in the PHP programming language which we^H^HI love! :)
Other bits and pieces are done with JSON, Subversion, and BASH.
Ubuntu
This software was developed and tested on Ubuntu 18.04 LTS.
JSON
We use the JavaScript Object Notation format for our configuration data.
BASH
The bash shell is our Unix shell of choice. You don't need Bash to run svnman but it is used by our build scripts.
$PATH
When you install svnman you should make sure a symlink to bin/svnman.php
is in your $PATH environment variable.
$HOME
We rely on the $HOME environment variable being set to indicate your home directory. We need to know where your home directory is so that we can save and load your configuration data (see config).
PHPBOM
Our svnman utility has first-class support for our PHPBOM library. Basically when you use svnman to create a new project you can optionally have the PHPBOM library automatically included in your project.
Bugslist
We use Bugslist to generate our TODO list.
VERSION
Supported version numbers are in the format MAJOR.MINOR.PATCH. See versioning for more info.
NOTE
We often put notes in our code. The format is something like this:
// {date} {user} - NOTE: {note}
Where {date} is in ISO 8601 format (yyyy-mm-dd) and the {user} is the username of the person who left the note. A {note} is just some text that aims to be helpful and usually relates to some code that follows the note itself.
We also use a similar format for TODO items etc. These formats are supported by bugslist which we use to generate documentation.
Notes
Notes for implementers
If you are interested in incorporating this software into your project, here's what you need to know.
Installation
The recommended way to install this software is by checking out the 'trunk' version from source control.
In order to run svnman you should create an svnman
symlink somewhere in your $PATH and point it to bin/svnman.php
.
So a full installation might look something like this:
$cd ~/software
$svn co https://www.progclub.org/svn/pcrepo/svnman/trunk svnman
$cd ~/bin
$ln -s ~/software/svnman/bin/svnman.php svnman
You might also need to install some dependencies, such as:
# apt install php-cli subversion
This software has been developed and tested on Ubuntu 18.04 LTS GNU/Linux. It will probably work in other Unix environments and it will definitely be broken on Windows. (If you'd like to make it work on Windows we will accept your patch!)
Configuration
After you install svnman you might like to configure one or more repository aliases using the config subcommand.
For example the config for 'pcrepo' might be something like this:
$ svnman config \
--alias pcrepo \
--location https://www.progclub.org/svn/pcrepo \
--working-base ~/repo/svn/pcrepo \
--viewvc https://www.progclub.org/pcrepo
Shell integration
The svnman software has been designed for maximal integration with your Unix shell, particularly BASH. We recommend adding the following shell functions to your .bashrc (or similar). These functions provide a simpler command-line interface to svnman and their output is used to change directory upon completion, which is quite handy.
pcrepo-create() { svnman-create pcrepo "$@"; } svnman-create() { local repo="$1"; local project_name="$2"; shift; [ -z "$repo" ] && { echo "repo alias required"; return 1; } [ -z "$projtect_name" ] && { echo "project name required"; return 2; } pushd "$( svnman create --repo "$repo" --project-name "$@" )" >/dev/null 2>&1 } bump-minor() { pushd "$( svnman bump-minor "$@" )" >/dev/null 2>&1 } bump-major() { pushd "$( svnman bump-major "$@" )" >/dev/null 2>&1 }
All of the above functions are supposed to run with the current working directory pointing to a Subversion working copy. The bump-minor
and bump-major
commands don't require any arguments, and the svnman-create
command takes at least two args, the first being the repo alias and the second being the project name. Tne pcrepo-create
command automatically supplies the first argument to svnman-create
, so pcrepo-create
only requires one argument, being the project name.
So for example the PHPBOM project would have been created like this:
$ pcrepo-create phpbom
Note that these functions assume you have configured appropriate repository aliases (such as 'pcrepo') for use with the --repo argument.
Notes for developers
If you're looking to set up a development environment for this project, here's what you need to know:
$ svn co https://www.progclub.org/svn/pcrepo/svnman/branches/1.0 svnman-1.0
You can then run the unit tests like this:
$ cd svnman-1.0 && bin/test/test.sh
Note that you may need to install some dependencies, such as:
# apt install php-cli subversion
Notes for ProgClub administrators
To release a version of this project use the software itself.
First, run maintenance and commit any changes:
$ svnman commit
Then run the release:
$ bin/dev/release.sh
You will be prompted to update the project documentation.
Tasks
TODO
MEDIUM
- TODO: bin/dev/gen.sh: 84: generate with wiki links to source files...
- TODO: bin/dev/gen.sh: 86: generate tasks.wiki with TODO and Done sections...
- TODO: bin/test/test.sh: 485: we need much more extensive testing here. Make sure all subcommands get used and in various ways.
- TODO: bin/test/test.sh: 1432: probably need more happy path tests...
- TODO: src/code/svnman.php: 786: this spec should probably be moved into the Settings class and be used for input validation.
- TODO: src/code/svnman.php: 1570: this program needs better reporting. The current "all or nothing" ouutput is no good and needs to be revised. Basically there should be no output on success and only a brief error message on failure. The current verbose output can be retained for if a --debug or --verbose option is added.
- TODO: src/code/svnman.php: 1576: need to support other version file formats. Especially *.cfg and maybe *.ini formats. Note that *.cfg file format is a key value format that is compatible with Unix shell environment config.
- TODO: src/code/svnman.php: 1580: add a --debug command-line option. Be less verbose if it's not specified.
- TODO: src/code/svnman.php: 1583: add a 'latest-branch' subcommand that reports the current branch and the latest branch (and if they're the same or different).
- TODO: src/code/svnman.php: 1591: add support for 'browse' subcommand.
- TODO: src/code/svnman.php: 1593: clean up after ourselves, delete temp files and directories...
- TODO: src/code/svnman.php: 1596: add support for --tarball generation during release.
- TODO: src/code/svnman.php: 1601: add a --json argument which causes program output to be in stable JSON format for better software integration options. Enable JSON output for 'version', 'errors', and 'help' too.
- TODO: src/code/svnman.php: 1610: in gen-vars subcommand support --prefix option for putting env var names in a namespace...
- TODO: src/code/svnman.php: 1617: add --error ERROR_CODE|ERROR_NAME option to `svnman errors` which will print out detailled error information for the particular error indicated.
- TODO: src/code/svnman.php: 1621: add a --bug BUG_NUMBER argument. The BUG_NUMBER to be included in commit messages.
- TODO: src/code/svnman.php: 1624: when updating version file, don't just update a single file, but update all version files, allowing for there to be multiple version file formats used in a single project. This will entail verifying the all version files agree with each other as regards the version number.
- TODO: src/code/svnman.php: 1630: grep for ERR_ constants and report if <= 1 (i.e. declared but unused).
- TODO: src/code/svnman.php: 1633: svnman get-error-code --error-name ERROR_NAME
- TODO: src/code/svnman.php: 1635: svnman get-error-name --error-code ERROR_CODE
- TODO: src/code/svnman.php: 1637: svnman get-error-info --error ERROR_NAME|ERROR_CODE
- TODO: src/code/svnman.php: 1639: if --phpbom is nominated during `svnman create` then write the version file to src/code/0-bootstrap/2-version.php and not to inc/version.php.
- TODO: src/code/svnman.php: 1646: only output stack trace on error if --debug is specified or error hint === PLEASE_INFORM.
- TODO: src/code/svnman.php: 1652: support single and double quotes on strings in *.cfg files
- TODO: src/code/svnman.php: 1655: add support for a 'get' subcommand. Will get the latest version (or a specified version) of a project from Subversion and check it out into a local working copy (usually under the working base). If no project name is specified then list available projects.
LOW
- THINK: src/code/class/Manager.php: 1269: do we want to just automatically mkdir -p the working base..?
- THINK: src/code/svnman.php: 1587: do we want an optional argument --version-file for manually nominating the version file..? (At the moment we prefer convention over configuration.)
- THINK: src/code/svnman.php: 1605: enable JSON output for tests?
- THINK: src/code/svnman.php: 1607: consider adding an interactive mode that will confirm options or ask questions.
- THINK: src/code/svnman.php: 1613: if we're gonna allow refactoring of error name constants we might want a compatibility thing that aliases old/deprecated names to new names. But such a facility isn't necessary yet.
- THINK: src/code/svnman.php: 1643: think about what other files/directories we might want to create upon `svnman create` if --phpbom is specified.
- THINK: src/code/svnman.php: 1649: hint for unauthorised --non-interactive `svn` operations which fail: "please authenticate"
Done
Stuff that's done. Latest stuff on top.