histofile

_images/histofile.png

histofile is a small tool to aid in the management of NEWS files for a project.

The intention is that each time you commit or merge a change that warrants an entry in your NEWS file you also add a new histofile data file. When it is time to cut a new release you tell histofile, and it updates your NEWS file from your pre-existing entries.

This should save an enormous amount of time, as it reduces the need to scan through the commit log then manually create a NEWS file.

The data files are stored as plaintext in your chosen directory with one file per entry, which means unlike a developer updated NEWS file in your repository histofile should work easily across merges [1].

It is written in moonscript, and requires v0.3.0 or later. histofile is released under the GPL v3.

Git repository:https://github.com/JNRowe/histofile/
Issue tracker:https://github.com/JNRowe/histofile/issues/
Contributors:https://github.com/JNRowe/histofile/contributors/

Contents

Background

One of the most important aspects of creating a new software release is updating your users with all the fancy new features, deprecated functionality and breaking changes that may have happened. Depressingly, this important task is often rushed in five minutes or skipped entirely. It can definitely be annoying having to pour over hundreds of commits to find the important user facing items, and there should be a tool to automate some of that.

The features I need in a tool for this task are:

  • Support for multiple branches without having to spend three hours shuffling merges
  • Easily accessible data, in a format that can be processed simply
  • Ability to work off-line, because those times are considerably more common than some people seem to think
  • Works on all the platforms I regularly use; desktop, mobile phone, ZipIt, and more

Now histofile is born, and I should be able to realise those dreams!

Philosophy

NEWS entries should be:

  • Written when the commit is made, you shouldn’t need to scan diffs from six months ago.
  • Self-contained, you shouldn’t need to handle a heap of merge conflicts because you have multiple branches or developers.
  • Easy to generate
  • Easy to mass process

Usage

The histofile script is the main workhorse of histofile.

See Getting started for basic usage examples.

Options

--version

Show the version and exit.

-d <directory>, --directory=<directory>

Database location, defaults to .histofile.

--help

Show help message and exit.

Commands

list - List history entries
histofile list [--help]
--help

Show help message and exit.

new - Add new history entry
histofile new <entry>
--help

Show help message and exit.

update - Update history file
histofile update [--help] <version> <file>
-d <date>, --date <date>

Date of release, defaults to today.

-o <file>, --output <file>

Output file name.

-t <name>, --template <name>

Template name, defaults to “default”

--list-templates

List available templates.

-k, --keep

Keep old data files after update (default when writing to stdout).

--help

Show help message and exit.

Getting started

Basic usage

The command interface is hopefully quite intuitive. The following is a sample session:

$ histofile new "Add support for cake baking"
$ histofile new "Removed support for window cleaning"
$ histofile list
2016-02-10T12:03:00     Add support for cake baking
2016-02-10T12:03:05     Removed support for window cleaning
$ histofile update --output - 0.2.0 NEWS.rst
<fancy new NEWS.rst>
$ histofile update 0.2.0 NEWS.rst
<NEWS.rst is updated in place>

Help on individual subcommands is available via histofile <subcommand> --help or in the Usage document.

Configuration

histofile ships with what the maintainer hopes are reasonable defaults, but can be configured in various ways.

histofile will read argument defaults from .histofile.json or the file pointed to by HISTOFILE_CONFIG. The file should be a valid JSON document, and can contain the following items:

Variable Type Description
directory str The directory to read and write NEWS entries to
filename str The filename to use as the NEWS file
keep bool Whether to keep the entries after writing updates
template_name str The template set used to render the NEWS file

For example, a configuration file could contain the following:

{
    "directory": "/out/of/tree/storage",
    "filename": "awful_name.md"
}

histofile

Manage version history files

SYNOPSIS

histofile [option]... <command>

DESCRIPTION

histofile is a small tool to aid in the management of NEWS files for a project.

OPTIONS

--version Show the version and exit.
-d <directory>, --directory <directory>
 Location to store history entries, defaults to .histofile.
--help Show help message and exit.

COMMANDS

list

List history entries.

--help Show help message and exit.
new

Add new history entry.

--help Show help message and exit.
update

Update history file.

-d <date>, --date <date>
 Date of release, defaults to today.
-o <file>, --output <file>
 Output file name.
-t <name>, --template <name>
 Template name, defaults to “default”
--list-templates
 List available templates.
-k, --keep Keep old data files after update (default when writing to stdout).
--help Show help message and exit.

BUGS

None known.

AUTHOR

Written by James Rowe

COPYING

Copyright © 2016 James Rowe.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Frequently Asked Questions

Can I use an editor to write entries?

I’ve thought about it a lot, and I’m not convinced it is a good idea to make histofile new call an editor with empty arguments. Having to think about fitting the entry in to a reasonable size to write at the shell prompt just feels right; NEWS entries just shouldn’t be essays.

That said, you can edit the files after creation or use your shell’s command substitution to work around my possibly misplaced ideals.

I’m not totally opposed to it however, and would likely accept a pull request that implements it should someone feel strong enough about it.

Why not Markdown?

There is no reason Markdown-style output can’t be supported, it is just the default template that uses reST formatting.

The simple reason reST output was chosen at the start is that no project I work on would welcome the addition of a Markdown file. The major sticking point being that nobody appears to know what constitutes a valid Markdown document. Even the simple matter of whether to wrap lines or not is up for discussion with every parser.

That said, nothing stops you from implementing a Markdown-ish generating template and opening a pull request. In fact, adding a GitHub Flavoured Markdown template is kind of on my TODO list, but admittedly very low as I have no personal use for it myself.

Alternatives

Before diving in and spitting out this package I looked for alternatives, but couldn’t find anything beyond suggestions about formatting to make a developer updated NEWS file more manageable.

If I have missed something please drop me a mail.

Templates

Templates are implemented using the excellent etlua package.

Files

Each template set is a pair of files; marker and main.etlua.

marker

The marker file contains a “magic” string, that is used to find the location in the NEWS file to insert new entries.

It is matched with lua‘s string.match function, and should be as tight as possible to prevent false matches. The default template’s marker is %.%. contents:: which matches a reST table of contents directive.

main.etlua

The main.etlua file is the template that is used to generate the header and individual entries for the NEWS file.

It is provided with the following data:

Variable Description
date The data provided by the user with the histofile update --date option.
entries The new entries to add to the output.
old_entries The previously existing data in the NEWS file.
version The version provided by the user with the version argument.

The following formatting functions are provided for convenience:

Function Description
stylise() Basic terminal formatting support
wrap_entry() A simple line wrapper for text inputs

Along with the following variables for formatting output:

Variable Type Description
bg string indexed table Colours to set terminal background.
bold string Set terminal to bold
fg string indexed table Colours to set terminal foreground.
form_feed string Force a form feed
reset string Reset terminal formatting
underline string et terminal to underline

Configuration via environment variables

histofile defaults for some options can be configured via environment variables. The design purpose for supporting these environment variables is to make it easy for users to configure per-project defaults using shell hooks.

HISTOFILE_CONFIG

This should point to a valid JSON file containing option defaults, see Configuration for the accepted keys and their possible values.

Release HOWTO

Prepare release

  • Update the version data in version.moon
  • Update NEWS.rst, with histofile ;)
  • Commit the release notes and version changes
  • Create a signed tag for the release
  • Push the changes, including the new tag, to the GitHub repository
  • Create new release on GitHub

Announce release

Check the generated tarballs for errors; missing files, stale files, &c

You should also perform test installations, to check the experience histofile users will have.

API documentation

Note

The documentation in this section is aimed at people wishing to contribute to histofile, and can be skipped if you are simply using the tool from the command line.

Command line

Note

The documentation in this section is aimed at people wishing to contribute to histofile, and can be skipped if you are simply using the tool from the command line.

load_templata_data(name)

Load template data.

Parameters:name – Template name to load
Returns:Template data
read_config()

Read repository configuration.

Returns:Configuration data
parse_args(conf)

Parse command line arguments.

Parameters:conf – Configuration defaults to apply
Returns:Processed command line arguments

Entry handling

Note

The documentation in this section is aimed at people wishing to contribute to histofile, and can be skipped if you are simply using the tool from the command line.

wrap_entry(text, width=72, initial_indent="", subsequent_indent=initial_indent)

Wrap text for output.

Parameters:
  • text – Text to format
  • width – Width of formatted text
  • initial_indent – String to indent first line with
  • subsequent_indent – String to indent all but the first line with
Returns:

Wrapped text

find_entries(path)

List valid history entries.

Parameters:path – Path to search
Returns:Matching entries
name_to_time(f)

Read time from filename

Parameters:f – Filename to scan
Returns:ISO-8601 formatted date string

File handling

Note

The documentation in this section is aimed at people wishing to contribute to histofile, and can be skipped if you are simply using the tool from the command line.

find_old_entries(data, marker_string)

Find old NEWS entries.

Parameters:
  • data – Data to operate on
  • marker_string – Match location to find old entries
Returns:

Old entries

write_output(file, content)

Write output to file or stdout.

Parameters:
  • file – Output file name
  • content – Strings, or table of strings, to write
Returns:

0 on success, (errno, reason) on failure

Interface support

Note

The documentation in this section is aimed at people wishing to contribute to histofile, and can be skipped if you are simply using the tool from the command line.

main()

Main entry point.

Calls os.exit on completion.

commands table
list(args)

List history entries.

Parameters:args – Parsed arguments
Returns:Exit code suitable for shell
new(args)

Add new history entry.

Parameters:args – Parsed arguments
Returns:Exit code suitable for shell
update(args)

Update history file.

Parameters:args – Parsed arguments
Returns:Exit code suitable for shell

Template support

Note

The documentation in this section is aimed at people wishing to contribute to histofile, and can be skipped if you are simply using the tool from the command line.

template_vars = {…}

Template variables and functions

Utilities

Note

The documentation in this section is aimed at people wishing to contribute to histofile, and can be skipped if you are simply using the tool from the command line.

ANSI_FG_COLOURS = {…}

Terminal escapes for colours.

Foreground colour control codes

ANSI_BG_COLOURS = {…}

Terminal escapes for colours.

Background colour control codes

stylise(text, colour=nil, attrib={bold: false, underline: false}, force=false)

Generate stylised output for the terminal.

Parameters:
  • text – Text to format
  • colour – Colour to use
  • attrib – Formatting attributes to apply
Returns:

Stylised output

success(text, bold=true)

Standardised success message.

Parameters:
  • text – Text to stylise
  • bold – Use bold output
fail(text, bold=true)

Standardised failure message.

Parameters:
  • text – Text to stylise
  • bold – Use bold output
warn(text, bold=true)

Standardised warning message.

Parameters:
  • text – Text to stylise
  • bold – Use bold output

Indices and tables

[1]git, and some other VCSes, do support per-file merge tools that can make a simple edited file approach work. Using that may be the best option for you!