Scripts for repository management

My way of working

Like everyone else, I tend to refer to the things I work on as "projects".

In order to take full advantage of my daily experiences with the things I have made, I have the scripts / symlinks that they start point to the version that I also develop on. That gives me immediate feedback about the things I'm adjusting. I call this my "working" environment.

When I am satisfied - and that includes performing unit tests - I transfer the stuff to a repository that I basically never make adjustments in, so that I also have a stable version on my system. I call this my "central" environment.

From here I can finally transfer the stuff to GitHub so that I also saved a version outside my laptop, just in case. The name for this environment is "remote".

Periodically checking everything at once has my preference because it gives me the opportunity to think about whether I want to commit things that I have not yet committed or rather rollback and approach differently.

Inspecting changes and propagating them

A lot of these commands take an option -n to specify on or more repository names. If more than one, they must be separated with comma's, without spaces following them (which my muscle memory doesn't like). Omitting this argument means processing all (active) repositories.

To keep track of the status of the changes I make from time to time I use the followng function:

binfab repo.check-local

Because I use it so often I wrapped the invocation in the easier to use "repocheck". This task cycles through all my repositories and executes git status in them to see if there have been uncommitted or unpushed changes.

Output is a summation like

/docs/scripts/repo-py/repocheck-output.png

Details are saved to a file (basically the collected output of git status and git log) that you can view using the command

binfab repo.check-local-changes

which opens the file in a text editor.

I made a similar function for the next stage:

binfab repo.check-remote

that does the same as "check-local" but for the "central" repositories. Fortunately Git saves a lot of information in the pushing directory so that you don't have to go to the remote server. When I wasn't aware of this (it was also in my Mercurial days) I had made a mechanism for this using what I called "tip-files" that were updated during the push to remote.

Check-local is a kind of exploration after which I go over the uncommitted stuff repo by repo to see if I should catch up on anything; when I'm done and ready to migrate the changes I can do that with

binfab repo.push-local [--exclude=<reponames>] [--include=<reponames>]

which does the same as "check-local" but also migrates (pushes) the committed changes to the next ("central") environment (repo).

Because I don't always want to migrate all that is ready I made it possible to name the repo's that to include or exclude in the migration.

This also has a variant that operates on the "central" environment:

binfab repo.push-remote [--exclude=<reponames>] [--include=<reponames>]

At one time I a;so had a variant called "pushthru" that performed push_local and push_remote after another but I decided that this didn't need to exist in this collection; I do have a separate script called repopush that does the same, which I excute when I'm satisfied with the state of things after repocheck.

At another time I wanted to do something with versions or tags so I built a function to create a condensed project history from the repository logs:

binfab repo.overview --name=<reponame> [--outtype=<output-type>]

I did a lot of coding for that and later I realized that some form of git log could give me exactly that and besides, I don't do anything with versions anymore.

Development activities

I wanted to make it possible to call several tools that I often use for a give repo so I build some functions that take a repo name as a first argument, check the arguments and then call a tool accordingly. I then used these functions in my scripts for session management.

One of these is viewing project notes:

binfab repo.dtree --name=<reponame>

I can open a (larger than default) teminal session directly in a project's root directory using

binfab repo.prshell --name=<reponame>

Opening one or more files belonging to a given projects for editing with VIm can be done using

binfab repo.predit -p <project> <source> [-t]

<source> can be an actual filename (relative to the project root so e.g. "src/main.py" would suffice) but also a name known to one of the project's configuration files - in .sessionrc for instance the name "progs" stands for all the project's program files and in .rurc "main" or "qtgui" often stand for specific modules. The "-t" addition searches .rurc for the accompanying module containing unittests.

The same mechanism I also applied for opening my search program (FileFindR); this I can call up with

binfab repo.prfind -p <project> <source> [-t]

To work on a project's readme document I have

binfab repo.preadme --name=<reponame>

to open it in a text editor, and

binfab repo.rreadme --name=<reponame>

to open it in an rst viewer.

Listing the branches of a project repo can be done with

binfab repo.list-branches

which isn't much more than a wrapper around git branch IIRC.

To process all the repos together there is

binfab repo.mee-bezig

to open a treedocs document with overviewy information about all projects. Among others I use it to keep track of which projects have a severe lack of unittests.

There are also some tasks to search in the files of all projects:

  • binfab repo.search-all --find=<search-term> [--rebuild] to search in all tracked python files in all repos (I also built a shortcut script: pfind -as <search-term>)

  • binfab repo.search-p --find=<search-term> [--rebuild] - the same but only for program code (alternative: pfind -ps <search-term>)

  • binfab repo.search-t --find=<search-term> [--rebuild] - this one searches only test modules (can also be done with pfind -ts <search-term>)

Unit testing

A script to run unittests while keeping track of testcoverage was already present. The following function uses a project's .rurc configuration to determine which test you want to execute:

binfab repo.runtests --name=<reponame> [<test>]

Additionally I have some functions to produce statistics:

binfab repo.find-failing-tests

execute unittests and report the failing ones for one or more given repositories

binfab repo.find-test-errors

execute unittests and report the tests that have errors

binfab repo.find-test-stats

execute unittests and show the coverage for one or more given repositories

Miscellaneous

Finally some functions that have to with viewing repositories:

binfab repo.qgit --name=<reponame>

Open a Git gui for a project. Could be an alternative for check-repo, I have to look into it some time.

binfab repo.add2gitweb [--names=<reponames>] [--frozen]

add a repository to the configuration so that it can be viewed using gitweb