diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2020-08-06 23:32:13 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2020-08-12 12:33:41 +0300 |
commit | 768727f37afa6fbb5082833a4c14c8134ec42122 (patch) | |
tree | 8c7b3d85f9735d8585781a45f9e61b15fdaa3530 | |
parent | 4c61819dedbc3547bf3f352809ecfb6a95ab8753 (diff) |
Add implementation
31 files changed, 948 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1631641 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +# This is a good default: files that are auto-detected by git to be text are +# converted to the platform-native line ending (LF on Unix, CRLF on Windows) +# in the working tree and to LF in the repository. +# +* text=auto + +# Use `eol=crlf` for files that should have the CRLF line ending both in the +# working tree (even on Unix) and in the repository. +# +#*.bat text eol=crlf + +# Use `eol=lf` for files that should have the LF line ending both in the +# working tree (even on Windows) and in the repository. +# +#*.sh text eol=lf + +# Use `binary` to make sure certain files are never auto-detected as text. +# +#*.png binary @@ -0,0 +1,7 @@ +This file contains information about the build2 authors for copyright +purposes. + +The copyright for the code is held by the contributors of the code. The +revision history in the version control system is the primary source of +authorship information for copyright purposes. Contributors that have +requested to also be noted explicitly in this file are listed below: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6bfc34f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,16 @@ +This project is part of the `build2` toolchain; see its +[Community](https://build2.org/community.xhtml) page for various ways to +contribute. + +The copyright for the code is held by the contributors of the code (see the +`AUTHORS` file). The code is licensed under permissive open source licensing +terms (see the `LICENSE` file). When you contribute code to this project, you +license it under these terms. Before contributing please make sure that these +terms are acceptable to you (and to your employer(s), if they have rights to +intellectual property that you create) and that the code being contributed is +your original creation. + +The revision history in the version control system is the primary source of +authorship information for copyright purposes. If, however, you would like +to also be noted explicitly, please include the appropriate change to the +`AUTHORS` file along with your contribution. @@ -0,0 +1,6 @@ +The easiest way to build this package is with the bpkg package manager: + +$ bpkg build bdep-util + +But if you don't want to use the package manager, then you can also build it +manually using the standard build2 build system. @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2014-2020 the build2 authors (see the AUTHORS file). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. @@ -0,0 +1 @@ +See https://git.build2.org/cgit/bdep-util/log/ for the change log. @@ -0,0 +1,20 @@ +This package contains extra build2 project management utilities. + +build2 is an open source, cross-platform toolchain for building and packaging +C++ code. Its aim is a modern build system and dependency manager for the C++ +language that provide a consistent, out of the box interface across multiple +platforms and compilers. For more information see: + +https://build2.org/ + +See the NEWS file for the user-visible changes from the previous release. + +See the LICENSE file for the distribution conditions. + +See the INSTALL file for the prerequisites and installation instructions. + +See the doc/ directory for documentation. + +Send questions, bug reports, or any other feedback to the users@build2.org +mailing list. You can post without subscribing. See https://lists.build2.org +for searchable archives, posting guidelines, etc. diff --git a/bdep-util/.gitignore b/bdep-util/.gitignore new file mode 100644 index 0000000..7ecc5ca --- /dev/null +++ b/bdep-util/.gitignore @@ -0,0 +1,3 @@ +bdep-git-pre-commit +bdep-git-pre-commit-version-check +bdep-git-pre-commit-copyright-check diff --git a/bdep-util/buildfile b/bdep-util/buildfile new file mode 100644 index 0000000..5fc25c8 --- /dev/null +++ b/bdep-util/buildfile @@ -0,0 +1,38 @@ +# file : bdep-util/buildfile +# license : MIT; see accompanying LICENSE file + +import mods = libbutl.bash%bash{manifest-parser} +import mods += libbutl.bash%bash{standard-version} + +# @@ TMP Note that git-hooks/pre-commit, bdep-git-pre-commit, and +# bdep-git-pre-commit-copyright-check have no dependencies on any bash +# module. However, we add such dependencies for the bash module rule to +# match. Eventually, there will be a better way to achieve that (hints). +# + +# Note that git-hooks/pre-commit script just sources bdep-git-pre-commit. The +# reason to have both scripts is to be able to configure git's pre-commit hook +# via the core.hooksPath configuration value (should refer, for example, to +# the /usr/local/bin/bdep-git-hooks directory) and to import +# bdep-git-pre-commit, for example, for testing the installed hook. +# +git-hooks/ +{ + exe{pre-commit}: in{pre-commit} ../exe{bdep-git-pre-commit} $mods +} + +exe{bdep-git-pre-commit}: in{git-pre-commit} \ + exe{bdep-git-pre-commit-version-check \ + bdep-git-pre-commit-copyright-check} \ + $mods + +exe{bdep-git-pre-commit-version-check}: in{git-pre-commit-version-check} \ + $mods + +exe{bdep-git-pre-commit-copyright-check}: in{git-pre-commit-copyright-check} \ + $mods + +# Install the git pre-commit hook into bdep-git-hooks/ subdirectory of, say, +# /usr/bin/. +# +git-hooks/exe{pre-commit}: install = bin/bdep-git-hooks/ diff --git a/bdep-util/git-hooks/.gitignore b/bdep-util/git-hooks/.gitignore new file mode 100644 index 0000000..416634f --- /dev/null +++ b/bdep-util/git-hooks/.gitignore @@ -0,0 +1 @@ +pre-commit diff --git a/bdep-util/git-hooks/pre-commit.in b/bdep-util/git-hooks/pre-commit.in new file mode 100644 index 0000000..3339187 --- /dev/null +++ b/bdep-util/git-hooks/pre-commit.in @@ -0,0 +1,23 @@ +#! /usr/bin/env bash + +# file : bdep-util/git-hooks/pre-commit.in +# license : MIT; see accompanying LICENSE file + +# Forward the execution to the pre-commit script implementation. +# +# To enable the hooks globally run, for example: +# +# $ git config --global core.hooksPath /usr/local/bin/bdep-git-hooks +# +# Notes: +# +# - git passes no parameters to this kind of hooks. +# +# - git changes CWD to the git repository root directory for the hook process. +# +# - git command running from inside the hook sees files that should be +# auto-staged due to the -a git-commit option or similar as already staged. +# +trap 'exit 1' ERR + +source "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../bdep-git-pre-commit" diff --git a/bdep-util/git-pre-commit-copyright-check.in b/bdep-util/git-pre-commit-copyright-check.in new file mode 100644 index 0000000..2e0f982 --- /dev/null +++ b/bdep-util/git-pre-commit-copyright-check.in @@ -0,0 +1,73 @@ +#! /usr/bin/env bash + +# file : bdep-util/git-pre-commit-copyright-check.in +# license : MIT; see accompanying LICENSE file + +# Check copyright notices in the COPYRIGHT and LICENSE files and issue a +# warning if they don't include the current year. +# +# Specifically, look first for COPYRIGHT and then LICENSE in the root +# directory and all subdirectories in a project. +# +# Then in each file look for the first line matching the: +# +# ^Copyright (\([cC]\))? ... +# +# Regex, where "..." matches various year lists/ranges (e.g., "2010", "2010, +# 2011", "2010-2011", and their combinations; see the pattern below for +# details). Specifically, we don't consider Copyright notices that: +# +# - don't start at the very beginning of a line (indented, etc) +# - contain something other than years prior to the last year (names, etc) +# - wrap over multiple lines (long year list, etc) +# +# Note also that the current year is obtained in the UTC timezone. +# +trap 'exit 1' ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +# Recursively collect the COPYRIGHT and LICENSE files, skipping the LICENSE +# files in directories that contain the COPYRIGHT file. +# +# @@ Note that for now we assume that there are no spaces in the project file +# and directory names. +# +files=() + +fs=($(find . \( -type f -o -type l \) -name COPYRIGHT)) + +for f in "${fs[@]}"; do + files+=("$f") +done + +fs=($(find . \( -type f -o -type l \) -name LICENSE)) + +for f in "${fs[@]}"; do + d="$(dirname "$f")" + + if [ ! -f "$d/COPYRIGHT" ]; then + files+=("$f") + fi +done + +# Grep for the Copyright notice in the collected files and issue the warning +# if it is present and is outdated. +# +# @@ We should probably skip the COPYRIGHT/LICENSE files whose parent +# directories don't (recursively) contain staged files (think of projects +# with multiple packages, bundled third-party code, etc). Note that we can +# obtain the staged file list with the `git diff --name-only --cached` +# command. +# +current_year="$(date -u +'%Y')" + +for f in "${files[@]}"; do + year="$(sed -n -re 's%^Copyright( +\([cC]\))?[ 0-9,-]*[ ,-]([0-9]{4}).*$%\2%p' "$f" | head -n 1)" + + if [ -n "$year" -a "$year" != "$current_year" ]; then + info "WARNING: last copyright year in '${f#./}' is $year" + fi +done diff --git a/bdep-util/git-pre-commit-version-check.in b/bdep-util/git-pre-commit-version-check.in new file mode 100644 index 0000000..20cd4b0 --- /dev/null +++ b/bdep-util/git-pre-commit-version-check.in @@ -0,0 +1,220 @@ +#!/usr/bin/env bash + +# file : bdep-util/git-pre-commit-version-check.in +# license : MIT; see accompanying LICENSE file + +# Check that the changes being commited are compatible with the version state +# of the package(s). +# +# Specifically, fail if there are any changes staged for the released packages +# (the version is final or a stub) unless an appropriate version change is +# also staged. +# +# To achieve this, extract and compare versions corresponding to two states: +# the latest revision in the current branch (committed) and the potential +# result of the forthcoming commit (staged). +# +trap "{ exit 1; }" ERR +set -o errtrace # Trap ERR in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +@import libbutl/manifest-parser@ +@import libbutl/standard-version@ + +# Note that here and below a file in the existing repository revision is +# referred to as '<rev>:<path>' (for example 'HEAD:manifest') and in the +# staged revision as just ':<path>', where the path is relative to the project +# root directory (see gitrevisions(7) for details). + +# Return 0 if the specified file revision exists and 1 otherwise. +# +function file_exists () # [<rev>]:<path> +{ + local f="$1" + + if git cat-file -e "$f" 2>/dev/null; then # Repository object exists? + local t + t="$(git cat-file -t "$f")" + + if [ "$t" == "blob" ]; then + return 0 + fi + fi + + return 1 +} + +# Wrap libbutl manifest parsing functions to parse manifest revisions and to +# shorten names. Assumes that the specified manifest revision exists (for +# example, this is checked with the above file_exists() function). +# +function manifest_parser_start () # [<rev>]:<path> +{ + butl_manifest_parser_start < <(git cat-file -p "$1") + manifest_parser_ofd="$butl_manifest_parser_ofd" +} + +function manifest_parser_finish () +{ + butl_manifest_parser_finish +} + +# Find packages in the repository revision saving them into the specified by +# name associative array (needs to be declared prior to the function call) +# mapping the package names to the version/path pairs (for example "libfoo" -> +# "1.2.3 lib/foo"). Optionally, return only released packages. +# +# Note that the repository revisions can be in arbitrary states and the +# package manifests may not be necessarily present or valid. Thus, we consider +# a package to be present in the repository revision if its manifest +# (potentially referred to via the packages.manifest file) exists and contains +# a non-empty package name and the valid package version. Otherwise, for the +# staged revision, if it looks like it should be a package but something is +# missing, we warn. +# +function find_packages () # <rev> <result> [<released>] +{ + local rev="$1" + local -n r="$2" + local rel="$3" + + # Collect the potential package directories. + # + local ds=() + local n v + if file_exists "$rev:packages.manifest"; then + manifest_parser_start "$rev:packages.manifest" + + while IFS=: read -ru "$manifest_parser_ofd" -d '' n v; do + if [ "$n" == "location" ]; then + ds+=("${v%/}") + fi + done + + manifest_parser_finish + else + ds+=(.) + fi + + # Fill the resulting package map. + # + local d + for d in "${ds[@]}"; do + local m="$d/manifest" + local mr="$rev:$m" + + if ! file_exists "$mr"; then + + # Don't warn about absence of the root package manifest file, since this + # git repository may well not be a build2 package. + # + if [ -z "$rev" -a "$d" != "." ]; then + info "warning: package manifest file $m does not exist" + fi + continue + fi + + local name= + local version= + + manifest_parser_start "$mr" + + while IFS=: read -ru "$manifest_parser_ofd" -d '' n v; do + case "$n" in + name) name="$v" ;; + version) version="$v" ;; + esac + done + + manifest_parser_finish + + # Check if a non-empty package name is present. + # + if [ -z "$name" ]; then + if [ -z "$rev" ]; then + info "warning: package name is missing in $m" + fi + continue + fi + + # Check if a non-empty package version is present. + # + if [ -z "$version" ]; then + if [ -z "$rev" ]; then + info "warning: package version is missing in $m" + fi + continue + fi + + # Check if the package version is a valid standard version. + # + if ! butl_standard_version --is-version --is-not-earliest "$version"; then + if [ -z "$rev" ]; then + info "warning: package version '$version' in $m is not a valid standard version" + fi + continue + fi + + # Optionally, skip the unreleased version. + # + if [ ! $rel ] || butl_standard_version --is-not-snapshot "$version"; then + r["$name"]="$version $d" + fi + done +} + +# Collect the commited released packages. +# +declare -A committed_packages +find_packages 'HEAD' committed_packages true + +# Collect all the staged packages. +# +# Note that while we could bail out if there are no committed released +# packages, we will still collect the staged packages to potentially issue +# warnings about some of the manifest errors (empty package name, etc). +# +declare -A staged_packages +find_packages '' staged_packages + +# Iterate through the committed released packages and fail if there is a +# change but no version change staged for this package. +# +for p in "${!committed_packages[@]}"; do + read cv cd <<<"${committed_packages[$p]}" + + # Check if this is still a package in the staged revision. + # + if [[ -v staged_packages["$p"] ]]; then + read sv sd <<<"${staged_packages[$p]}" + + # If the package version didn't change, then check for any package changes + # and fail if there are any. + # + if [ "$sv" == "$cv" ]; then + + # Check that the package directory didn't change. + # + # If the package is moved, then detecting its changes becomes too + # complicated and we don't want to miss any. Let's keep it simple and + # deny moving the released packages (the user can always suppress the + # verification with --no-verify anyway). + # + if [ "$sd" != "$cd" ]; then + info "error: moving released package $p $cv" + info " info: use --no-verify git option to suppress" + exit 1 + fi + + # Check if the package has some staged changes in its directory. + # + if ! git diff-index --cached --quiet HEAD -- "$sd"; then + info "error: changing released package $p $cv without version increment" + info " info: use --no-verify git option to suppress" + exit 1 + fi + fi + fi +done diff --git a/bdep-util/git-pre-commit.in b/bdep-util/git-pre-commit.in new file mode 100644 index 0000000..27e76f3 --- /dev/null +++ b/bdep-util/git-pre-commit.in @@ -0,0 +1,17 @@ +#! /usr/bin/env bash + +# file : bdep-util/git-pre-commit.in +# license : MIT; see accompanying LICENSE file + +# Execute various pre-commit scripts in a git repository. +# +trap 'exit 1' ERR + +scr_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}")")" + +# Run each hook checking the exit status and bailing out if unsuccessful. We +# can just exec the last one. +# +"$scr_dir/bdep-git-pre-commit-version-check" + +exec "$scr_dir/bdep-git-pre-commit-copyright-check" diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..4a730a3 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,3 @@ +config.build +root/ +bootstrap/ diff --git a/build/bootstrap.build b/build/bootstrap.build new file mode 100644 index 0000000..8416065 --- /dev/null +++ b/build/bootstrap.build @@ -0,0 +1,10 @@ +# file : build/bootstrap.build +# license : MIT; see accompanying LICENSE file + +project = bdep-util + +using version +using config +using dist +using test +using install diff --git a/build/export.build b/build/export.build new file mode 100644 index 0000000..54f91e8 --- /dev/null +++ b/build/export.build @@ -0,0 +1,19 @@ +# file : build/export.build +# license : MIT; see accompanying LICENSE file + +$out_root/ +{ + include bdep-util/ +} + +switch $import.target +{ + case exe{bdep-git-pre-commit} + export $out_root/bdep-util/exe{bdep-git-pre-commit} + + case exe{bdep-git-pre-commit-version-check} + export $out_root/bdep-util/exe{bdep-git-pre-commit-version-check} + + case exe{bdep-git-pre-commit-copyright-check} + export $out_root/bdep-util/exe{bdep-git-pre-commit-copyright-check} +} diff --git a/build/root.build b/build/root.build new file mode 100644 index 0000000..122be6a --- /dev/null +++ b/build/root.build @@ -0,0 +1,6 @@ +# file : build/root.build +# license : MIT; see accompanying LICENSE file + +# Bash. +# +using bash diff --git a/buildfile b/buildfile new file mode 100644 index 0000000..efb049e --- /dev/null +++ b/buildfile @@ -0,0 +1,9 @@ +# file : buildfile +# license : MIT; see accompanying LICENSE file + +./: {*/ -build/} doc{INSTALL NEWS README} legal{LICENSE AUTHORS} manifest + +# Don't install tests or the INSTALL file. +# +tests/: install = false +doc{INSTALL}@./: install = false diff --git a/manifest b/manifest new file mode 100644 index 0000000..ba271a5 --- /dev/null +++ b/manifest @@ -0,0 +1,21 @@ +: 1 +name: bdep-util +version: 0.14.0-a.0.z +project: build2 +summary: extra build2 project management utilities +license: MIT +topics: project dependency management, build toolchain +description-file: README +changes-file: NEWS +url: https://build2.org +doc-url: https://build2.org/doc.xhtml +src-url: https://git.build2.org/cgit/bdep-util/tree/ +email: users@build2.org +build-warning-email: builds@build2.org +builds: all +builds: -windows ; Requires bash. +builds: -macos ; Requires bash >= 4.3. +requires: bash >= 4.3 +depends: * build2 >= 0.13.0 +depends: * bpkg >= 0.13.0 +depends: libbutl.bash [0.14.0-a.0.1 0.14.0-a.1) diff --git a/repositories.manifest b/repositories.manifest new file mode 100644 index 0000000..8f3604c --- /dev/null +++ b/repositories.manifest @@ -0,0 +1,6 @@ +: 1 +summary: extra build2 project management utilities + +: +role: prerequisite +location: ../libbutl.bash.git##HEAD diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..35ec43f --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,2 @@ +test/ +test-*/ diff --git a/tests/build/.gitignore b/tests/build/.gitignore new file mode 100644 index 0000000..4a730a3 --- /dev/null +++ b/tests/build/.gitignore @@ -0,0 +1,3 @@ +config.build +root/ +bootstrap/ diff --git a/tests/build/bootstrap.build b/tests/build/bootstrap.build new file mode 100644 index 0000000..c9187a6 --- /dev/null +++ b/tests/build/bootstrap.build @@ -0,0 +1,8 @@ +# file : tests/build/bootstrap.build +# license : MIT; see accompanying LICENSE file + +project = # Unnamed subproject. + +using config +using dist +using test diff --git a/tests/build/root.build b/tests/build/root.build new file mode 100644 index 0000000..90257ce --- /dev/null +++ b/tests/build/root.build @@ -0,0 +1,12 @@ +# file : tests/build/root.build +# license : MIT; see accompanying LICENSE file + +# Setup the targets that we are testing. +# +import git_pre_commit = bdep-util%exe{bdep-git-pre-commit} + +import git_pre_commit_version_check = \ + bdep-util%exe{bdep-git-pre-commit-version-check} + +import git_pre_commit_copyright_check = \ + bdep-util%exe{bdep-git-pre-commit-copyright-check} diff --git a/tests/buildfile b/tests/buildfile new file mode 100644 index 0000000..fb17c95 --- /dev/null +++ b/tests/buildfile @@ -0,0 +1,24 @@ +# file : tests/buildfile +# license : MIT; see accompanying LICENSE file + +define common: file +common{*}: extension = testscript + +commons = git-common git-pre-commit-common + +./: testscript{* -{$commons}} common{$commons} + +testscript{git-pre-commit}@./: $git_pre_commit +{ + test = $git_pre_commit +} + +testscript{git-pre-commit-version-check}@./: $git_pre_commit_version_check +{ + test = $git_pre_commit_version_check +} + +testscript{git-pre-commit-copyright-check}@./: $git_pre_commit_copyright_check +{ + test = $git_pre_commit_copyright_check +} diff --git a/tests/git-common.testscript b/tests/git-common.testscript new file mode 100644 index 0000000..aa90f3d --- /dev/null +++ b/tests/git-common.testscript @@ -0,0 +1,17 @@ +# file : tests/git-common.testscript +# license : MIT; see accompanying LICENSE file + +# Set commonly-used variables and create an empty git repository that will be +# copied by subsequent tests and scope setup commands. +# +g = git >! 2>&1 +gp = $g -C prj +ga = $gp add +gr = $gp rm + ++$g init prj &prj/*** + ++$gp config user.name 'Test Script' ++$gp config user.email 'testscript@example.com' + +clone_prj = cp --no-cleanup -r ../prj ./ &prj/*** diff --git a/tests/git-pre-commit-common.testscript b/tests/git-pre-commit-common.testscript new file mode 100644 index 0000000..ae8b9d4 --- /dev/null +++ b/tests/git-pre-commit-common.testscript @@ -0,0 +1,13 @@ +# file : tests/git-pre-commit-common.testscript +# license : MIT; see accompanying LICENSE file + +# Set commonly-used variables and configure git to call the hook being tested. +# Assume that git-common.testscript is already included. +# +gc = $gp commit -a --allow-empty-message -m '' + +hooks_dir=$~/hooks ++mkdir $hooks_dir ++$gp config core.hooksPath $hooks_dir + ++ln -s $0 $hooks_dir/pre-commit diff --git a/tests/git-pre-commit-copyright-check.testscript b/tests/git-pre-commit-copyright-check.testscript new file mode 100644 index 0000000..f8e51f5 --- /dev/null +++ b/tests/git-pre-commit-copyright-check.testscript @@ -0,0 +1,25 @@ +# file : tests/git-pre-commit-copyright-check.testscript +# license : MIT; see accompanying LICENSE file + +.include git-common.testscript git-pre-commit-common.testscript + +: basic +: +{ + $clone_prj; + + cat <<EOI >=prj/LICENSE; + Copyright (c) 2014-2019 the build2 authors. + EOI + $ga .; + + $gc 2>>EOE; + WARNING: last copyright year in 'LICENSE' is 2019 + EOE + + date +"%Y" | set year; + cat <<"EOI" >=prj/LICENSE; + Copyright (c) 2014-$year the build2 authors. + EOI + $gc +} diff --git a/tests/git-pre-commit-version-check.testscript b/tests/git-pre-commit-version-check.testscript new file mode 100644 index 0000000..28e4efc --- /dev/null +++ b/tests/git-pre-commit-version-check.testscript @@ -0,0 +1,263 @@ +# file : tests/git-pre-commit-version-check.testscript +# license : MIT; see accompanying LICENSE file + +.include git-common.testscript git-pre-commit-common.testscript + ++bash --version >&2 2>! # For troubleshooting. + +: multi-package-project +: +{ + $clone_prj; + + touch prj/TODO; + $ga .; + $gc; # Initial commit. + + echo '@@' >=prj/TODO; + $gc; # No committed packages.manifest. + + cat <<EOI >=prj/packages.manifest; + : 1 + location: libfoo/ + : + location: libbar/ + : + location: libbaz/ + EOI + $ga .; + + $gc 2>>EOE; # packages.manifest is staged. + warning: package manifest file libfoo/manifest does not exist + warning: package manifest file libbar/manifest does not exist + warning: package manifest file libbaz/manifest does not exist + EOE + + echo '@@ todo' >=prj/TODO; + + # packages.manifest is committed but there are no package manifests. + # + $gc 2>>EOE; + warning: package manifest file libfoo/manifest does not exist + warning: package manifest file libbar/manifest does not exist + warning: package manifest file libbaz/manifest does not exist + EOE + + mkdir prj/libfoo prj/libbar prj/libbaz; + cat <<EOI >=prj/libfoo/manifest; + : 1 + name: libfoo + version: 1.2.3-a.1.z + summary: Foo + EOI + cat <<EOI >=prj/libbar/manifest; + : 1 + name: libbar + version: 1.2.3 + summary: Bar + EOI + cat <<EOI >=prj/libbaz/manifest; + : 1 + name: libbaz + version: 0+1 + summary: Baz + EOI + $ga .; + + $gc; # Same as above plus the package manifests are + # staged. + + echo '@@ TODO' >=prj/TODO; + + $gc; # Packages are committed but the staged change + # goes outside the package directories. + + touch prj/libfoo/TODO prj/libbar/TODO prj/libbaz/TODO; + $ga libfoo/TODO; + + $gc; # Package with an open version (snapshot) is + # changed. + + $ga libbar/TODO; + + $gc 2>>EOE != 0; # Package with a final version is changed. + error: changing released package libbar 1.2.3 without version increment + info: use --no-verify git option to suppress + EOE + + sed -i -e 's/^(version:).+$/\1 1.2.4-a.1.z/' prj/libbar/manifest; + + $gc; # Open package development circle. + + echo '@@' >=prj/libbar/TODO; + + $gc; # Development cycle is open. + + $ga libbaz/TODO; + + $gc 2>>EOE != 0; # Package with a stub version is changed. + error: changing released package libbaz 0+1 without version increment + info: use --no-verify git option to suppress + EOE + + sed -i -e 's/^(version:).+$/\1 0+2/' prj/libbaz/manifest; + + $gc; # Release the stub package revision. + + sed -i -e 's/^(version:).+$/\1 1.2.3/' prj/libfoo/manifest; + + $gc; # Release new version. + + echo '@@ todo' >=prj/libfoo/TODO; + + $gc 2>>EOE != 0; # Package with a final version is changed. + error: changing released package libfoo 1.2.3 without version increment + info: use --no-verify git option to suppress + EOE + + $gr libfoo/manifest &!prj/libfoo/manifest; + + $gc 2>>EOE; # The manifest removal is staged (not a package now). + warning: package manifest file libfoo/manifest does not exist + EOE + + sed -i -e 's/^(version:).+$/\1 1.2.4/' prj/libbar/manifest; + + $gc 2>>EOE; # Release new version. + warning: package manifest file libfoo/manifest does not exist + EOE + + echo '@@ todo' >=prj/libbar/TODO; + + $gc 2>>EOE != 0; # Package with a final version is changed. + warning: package manifest file libfoo/manifest does not exist + error: changing released package libbar 1.2.4 without version increment + info: use --no-verify git option to suppress + EOE + + cat <<EOI >=prj/packages.manifest; + : 1 + location: libbaz/ + EOI + + $gc; # The package removal from packages.manifest is + # staged, so it's not a package anymore. + + cat <<EOI >=prj/packages.manifest; + : 1 + location: lib/baz/ + EOI + mkdir prj/lib; + mv prj/libbaz prj/lib/baz; + $ga .; + + $gc 2>>EOE != 0; # Package with a stub version is moved. + error: moving released package libbaz 0+2 + info: use --no-verify git option to suppress + EOE + + sed -i -e 's/^(version:).+$/\1 0+3/' prj/lib/baz/manifest; + + $gc # Release the stub package revision. +} + +: single-package-project +: +{ + $clone_prj; + + cat <<EOI >=prj/manifest; + : 1 + name: foo + version: 1.2.3 + summary: Foo + EOI + touch prj/TODO; + $ga .; + + $gc 2>|; # No committed manifest. + + echo '@@' >=prj/TODO; + + $gc 2>>EOE != 0; # Package with a final version is changed. + error: changing released package foo 1.2.3 without version increment + info: use --no-verify git option to suppress + EOE + + sed -i -e 's/^(version:).+$/\1 1.2.4-a.1.123/' prj/manifest; + + $gc; # Open package development circle. + + echo '@@ todo' >=prj/TODO; + + $gc; # Development cycle is open. + + sed -i -e 's/^(version:).+$/\1 1.2.4/' prj/manifest; + + $gc; # Release new version. + + echo '@@ TODO' >=prj/TODO; + + $gc 2>>EOE != 0; # Package with a final version is changed. + error: changing released package foo 1.2.4 without version increment + info: use --no-verify git option to suppress + EOE + + $gr manifest &!prj/manifest; + + # Make sure there is no warning. + # + $gc 2>:'' # The manifest removal is staged, so it's not a + # package anymore. +} + +: warnings +: +{ + +$clone_prj + + : no-name + : + { + $clone_prj; + + cat <<EOI >=prj/manifest; + : 1 + summary: Foo + EOI + $ga .; + + $gc 2>"warning: package name is missing in ./manifest" + } + + : no-version + : + { + $clone_prj; + + cat <<EOI >=prj/manifest; + : 1 + name: libfoo + summary: Foo + EOI + $ga .; + + $gc 2>"warning: package version is missing in ./manifest" + } + + : invalid-version + : + { + $clone_prj; + + cat <<EOI >=prj/manifest; + : 1 + name: libfoo + version: abc + summary: Foo + EOI + $ga .; + + $gc 2>"warning: package version 'abc' in ./manifest is not a valid standard version" + } +} diff --git a/tests/git-pre-commit.testscript b/tests/git-pre-commit.testscript new file mode 100644 index 0000000..8b8f140 --- /dev/null +++ b/tests/git-pre-commit.testscript @@ -0,0 +1,42 @@ +# file : tests/git-pre-commit.testscript +# license : MIT; see accompanying LICENSE file + +.include git-common.testscript git-pre-commit-common.testscript + +: version-check +: +{ + $clone_prj; + + cat <<EOI >=prj/manifest; + : 1 + name: foo + version: 1.2.3 + summary: Foo + EOI + touch prj/TODO; + $ga .; + $gc; # No committed manifest. + + echo '@@' >=prj/TODO; + + $gc 2>>EOE != 0 # Package with a final version is changed. + error: changing released package foo 1.2.3 without version increment + info: use --no-verify git option to suppress + EOE +} + +: copyright-check +: +{ + $clone_prj; + + cat <<EOI >=prj/LICENSE; + Copyright (c) 2014-2019 the build2 authors. + EOI + $ga .; + + $gc 2>>EOE + WARNING: last copyright year in 'LICENSE' is 2019 + EOE +} |