From 5abec837ec5ed5ec195a54c241d5389e07d6f26d Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Sun, 27 Jun 2021 12:51:33 -0700 Subject: [PATCH] Girocco/ValidUtil.pm: refactor valid branch name check The branch name checking regular expression has become more-or-less unreadable: /^\/|^\.|[\x00-\x1f \x7f\[\[~^"'"<>*?\\:]|\@\{|\.\.|\.lock$|\.$|\/$/ And is duplicated in three different places while not managing to catch all the restrictions enforced by Git (see `git help check-ref-format`). The fact that if you look closely at it you can even see it checking for the same disallowed character twice (the '[') character. This suggests it has become somewhat unmaintainable in its current form. One challenge is that it's used by the install-time-only Girocco::Validator module and at runtime by the Girocco::Project module. Its use by the Girocco::Validator module makes it particularly tricky to refactor since the Girocco::Validator module validates the Girocco::Config module which pretty much all the other currently existing Girocco modules "use". Therefore moving the validation expression into Girocco::Util will simply not work (because then Girocco::Validator would need to "use" that module which in turn "use"s Girocco::Config which Girocco::Validator is trying to validate -- a bad idea). Create a new Girocco::ValidUtil module that does not "use" any other modules but exports a suitable `valid_branch_name` function for use by other modules. Take this opportunity to explicitly list all the rules it enforces, fix the items it was failing to catch and make the regex much more readable and understandable by using the "/x" modifier. Signed-off-by: Kyle J. McKay --- Girocco/ValidUtil.pm | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Girocco/ValidUtil.pm diff --git a/Girocco/ValidUtil.pm b/Girocco/ValidUtil.pm new file mode 100644 index 0000000..6f285dc --- /dev/null +++ b/Girocco/ValidUtil.pm @@ -0,0 +1,56 @@ +# This package contains validation checks that are use'd by +# both Girocco::Validator (which is an install-only module) +# and by Girocco::Util (which is a runtime module). +# It MUST NOT use any other Girocco modules!!! +# (And really SHOULD NOT use any other modules either.) + +package Girocco::ValidUtil; + +use 5.008; +use strict; +use warnings; + +BEGIN { + use base qw(Exporter); + our @EXPORT = qw(valid_branch_name); +} + +# Return undef if input argument is undef +# Otherwise return true if the argument is considered a valid Git branch name +# as far as Girocco is concerned. The "branch name" is the part AFTER the +# initial "refs/heads/". In other words the ref "refs/heads/master" represents +# the "branch name" known as "master". +# This function expects the bare branch name (e.g. "master") to be passed to +# it for validation. Note that an empty branch name (i.e. "") is not valid. +# Branch naming rules (mostly the rules applied by `git check-ref-format` with +# a few Girocco extra restrictions thrown in): +# 1. MUST NOT start with or end with a '/'(0x2f) +# 2. MAY have hierarchical components which MUST be separated with '/'(0x2f) +# 3. MUST NOT have any empty components (the part between two '/'s) (i.e. '//') +# 4. MUST NOT have any component that starts with or ends with a '.'(0x2e) +# 5. MUST NOT have any component that ends with '.lock' (case-insensitively) +# 6. MUST NOT contain any characters with a value between 0x00 and 0x1f (inclusive) +# 7. MUST NOT contain any space (0x20), backslash (0x5c) or DEL (0x7f) characters +# 8. MUST NOT contain any globbing characters '?'(0x3f), '*'(0x2a), '['(0x5b) +# 9. MUST NOT contain any Git-special characters '~'(0x7e), '^'(0x5e), ':'(0x3a) +# 10. MUST NOT contain the Git-special sequence '..'(0x2e 0x2e) +# 11. MUST NOT contain the Git-special sequence '@{'(0x40 0x7b) +# 12. MUST NOT be the Git-special branch name '@'(0x40) +# 13. MUST NOT contain (Girocco-disallowed) any quote characters "'"(0x27) or '"'(0x22) +# 14. MUST NOT contain (Girocco-disallowed) any '<'(0x3c) or '>'(0x3e) characters +sub valid_branch_name { + my $b = shift; + defined $b or return undef; + $b ne "" or return ""; + return $b !~ m{ + ^/ | /$ | # rule 1 + // | # rules 2+3 + (?:^|/)[.] | [.](?:/|$) | # rule 4 + [.][lL][oO][cC][kK](?:/|$) | # rule 5 + [\x00-\x1f "'"*:<>?\[\\^~\x7f] | # rules 6+7+8+9+13+14 + [.][.] | [\@][\{] | # rules 10+11 + ^\@$ # rule 12 + }xo; +} + +1; -- 2.11.4.GIT