stampver 1.2.0

A tool for updating project version numbers
Documentation
# Version Stamping Tool (Rust Edition)

[![coverage](https://shields.io/endpoint?url=https://raw.githubusercontent.com/jlyonsmith/stampver-rs/main/coverage.json)](https://github.com/jlyonsmith/stampver-rs/blob/main/coverage.json)
[![Crates.io](https://img.shields.io/crates/v/stampver.svg)](https://crates.io/crates/stampver)
[![Docs.rs](https://docs.rs/stampver/badge.svg)](https://docs.rs/stampver)

A Rust package and command line tool for updating version information in ANY type of project.

- Define which files need to be updated
- Three types of actions; update in place, create or copy in existing files
- Use regular expressions to find and replace content in existing files
- Store and insert other information in addition to versions, such as copyrights, etc..
- Fully customize the type of version update operations that you want for your project
- Supports any type of versioning scheme that you wish to use

## Overview

Releasing a new project typically involves:

- Updating version numbers in `package.json`, `Cargo.toml`, plus any source code files
- Creating Git tags with version numbers
- Building and ensuring all tests pass
- Pushing changes to a cloud source repository, e.g. GitHub, GitLab, etc..
- Publishing the newly minted and versioned package to a cloud package repository.

All of the above steps can be simplified with the use of this tool.

To use the tool for your project, simply:

1. Place a `version.json5` file in your project root that:
     - Describes the files that hold version numbers in your project
     - Which of the three actions (update, write or copy-in) to perform on each file
     - The types of version update operations you want to perform (`incrMajor`, `incrMinor`, etc..)
2. Run `stampver` as part of your project's release script

Once you start using `stampver` you will be able to copy the `version.json5` file in from another project and tweak it slightly in order to get set up quickly.

## Command Line

The command line tool `stampver` is included in this crate using the `cli` feature flag, which is installed by default.

```text
USAGE:
    stampver [OPTIONS] [OPERATION]

ARGS:
    <OPERATION>    The versioning operation to perform

OPTIONS:
    -h, --help                  Print help information
    -i, --input <INPUT_FILE>    Specify the version file explicitly
    -u, --update                Actually do the update
    -V, --version               Print version information
```

The tool will describe the actions that it is taking on each file so you can check that it is doing what you expect.

## Expressions

This package uses the [evalexpr](https://crates.io/crates/evalexpr) to provide the ability to customize the different calculations and operations.  All functions are available as described in the `evalexpr` *except* the `regex` functions. `stampver` adds the following variables/functions:

| Identifier   | Argument Amount | Argument Types  | Description                                                              |
| ------------ | --------------- | --------------- | ------------------------------------------------------------------------ |
| `now::year`  | 0               |                 | Current UTC year                                                         |
| `now::month` | 0               |                 | Current UTC month                                                        |
| `now::day`   | 0               |                 | Current UTC day of the month                                             |
| `if`         | 3               | Boolean/Any/Any | If expression `a` is `true` then the value of `b`, else the value of `c` |

`stampver` uses the [Regex](https://crates.io/crates/regex) crate for regular expressions. You can use the amazing [Regex101](https://regex101.com/) site to develop and test your own regular expressions.  Use the PCRE2 flavor of regular expressions for the most compatability with the `Regex` crate.

## Schema File Format

Here's an annotated schema file format:

```json5
{
  vars: {
    major: 3,
    minor: 0,
    patch: 0,
    build: 20210902,
    revision: 0,
    sequence: 6,
    buildType: "test",
    debug: true,
  },
  calcVars: {
    nextBuild: "now::year * 10000 + now::month * 100 + now::day",
    nextSequence: "sequence + 1",
  },
  operations: {
    incrMajor: "major += 1; minor = 0; patch = 0; revision = 0; build = nextBuild",
    incrMinor: "minor += 1; patch = 0; revision = 0; build = nextBuild",
    incrPatch: "patch += 1; revision = 0; build = nextBuild",
    incrRevision: "revision += 1; build = nextBuild",
    incrSequence: "sequence += 1",
    setBetaBuild: 'buildType = "beta"',
    setProdBuild: 'buildType = "prod"',
  },
  targets: [
    {
      description: "JavaScript Files",
      files: ["src/version.js"],
      updates: [
        {
          search: '^(?P<begin>\\s*export\\s*const\\s*version\\s*=\\s*")\\d+\\.\\d+\\.\\d+(?P<end>";?)$',
          replace: 'begin + str::from(major) + "." + str::from(minor) + "." + str::from(patch) + end',
        },
        {
          search: '^(?P<begin>\\s*export\\s*const\\s*fullVersion\\s*=\\s*")\\d+\\.\\d+\\.\\d+\\+\\d+\\.\\d+(?P<end>";?)$',
          replace: 'begin + str::from(major) + "." + str::from(minor) + "." + str::from(patch) + "+" + str::from(build) + "." + str::from(revision) + end',
        },
      ],
    },
    {
      description: "Git Version Tag",
      files: ["scratch/version.tag.txt"],
      write: 'str::from(major) + "." + str::from(minor) + "." + str::from(patch)',
    },
    {
      description: "iOS PList",
      files: ["some-file.plist"],
      copyFrom: '"src/some-file" + if(buildType == "test", "-test", "-prod") + ".plist"',
    },
  ],
}
```

Because the format is [JSON5](https://json5.org/) and a superset of JSON you can freely use comments. It is recommended to use [Prettier](https://prettier.io/) or equivalent. This is not just to keep your file nicely formatted, but also because `stampver` needs to update the file it might get confused if the formatting is too different from the above.

The 4 main sections are as follows.

### `vars`

This is where the version information lives, so it is in effect a simple version database for your project.  This is also the only section that the tool rewrites when version information is updated.  It does it in such a way as to preserve comments, but the tool does expect the layout to be similar to the example above.

### `calcVars`

These are any variables that need to get generated *each time the tool runs*. This can include things like a `build` number that is based on the date, or a `nextSequence` number.  The values in this section are merged with the `vars`, so be wary of naming conflicts.

### `operations`

These are the different version operations for your project. `incrMajor`, `incrMinor`, `incrPatch` are typical, but you can add whatever makes sense for your project.

### `targets`

`targets` is an array of objects containing a `description`, an array of `files` to update and then an action which must be exactly one of:

- `updates` - An array of `{ search: , replace: }` objects.  `search` is a regular expression. It can contain at most two optional capture groups that **must be called** `begin` and `end`.  These can be used in the `replace` substitution string.
- `write` - Writes content to the target files.  The content is an expression.
- `copyFrom` - Copies a file from another file, relative to the location of the `version.json5` file.  The name of the other file is an expression.

## License

This package is distributed under the terms of the [Unlicense](http://unlicense.org/) license. See the [`UNLICENSE`](UNLICENSE) file for details.