Blame build-aux/gitlog-to-changelog

Packit Service 51e54d
eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
Packit Service 51e54d
  & eval 'exec perl -wS "$0" $argv:q'
Packit Service 51e54d
    if 0;
Packit Service 51e54d
# Convert git log output to ChangeLog format.
Packit Service 51e54d
Packit Service 51e54d
my $VERSION = '2012-07-29 06:11'; # UTC
Packit Service 51e54d
# The definition above must lie within the first 8 lines in order
Packit Service 51e54d
# for the Emacs time-stamp write hook (at end) to update it.
Packit Service 51e54d
# If you change this file with Emacs, please let the write hook
Packit Service 51e54d
# do its job.  Otherwise, update this string manually.
Packit Service 51e54d
Packit Service 51e54d
# Copyright (C) 2008-2014 Free Software Foundation, Inc.
Packit Service 51e54d
Packit Service 51e54d
# This program is free software: you can redistribute it and/or modify
Packit Service 51e54d
# it under the terms of the GNU General Public License as published by
Packit Service 51e54d
# the Free Software Foundation, either version 3 of the License, or
Packit Service 51e54d
# (at your option) any later version.
Packit Service 51e54d
Packit Service 51e54d
# This program is distributed in the hope that it will be useful,
Packit Service 51e54d
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 51e54d
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 51e54d
# GNU General Public License for more details.
Packit Service 51e54d
Packit Service 51e54d
# You should have received a copy of the GNU General Public License
Packit Service 51e54d
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 51e54d
Packit Service 51e54d
# Written by Jim Meyering
Packit Service 51e54d
Packit Service 51e54d
use strict;
Packit Service 51e54d
use warnings;
Packit Service 51e54d
use Getopt::Long;
Packit Service 51e54d
use POSIX qw(strftime);
Packit Service 51e54d
Packit Service 51e54d
(my $ME = $0) =~ s|.*/||;
Packit Service 51e54d
Packit Service 51e54d
# use File::Coda; # http://meyering.net/code/Coda/
Packit Service 51e54d
END {
Packit Service 51e54d
  defined fileno STDOUT or return;
Packit Service 51e54d
  close STDOUT and return;
Packit Service 51e54d
  warn "$ME: failed to close standard output: $!\n";
Packit Service 51e54d
  $? ||= 1;
Packit Service 51e54d
}
Packit Service 51e54d
Packit Service 51e54d
sub usage ($)
Packit Service 51e54d
{
Packit Service 51e54d
  my ($exit_code) = @_;
Packit Service 51e54d
  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
Packit Service 51e54d
  if ($exit_code != 0)
Packit Service 51e54d
    {
Packit Service 51e54d
      print $STREAM "Try '$ME --help' for more information.\n";
Packit Service 51e54d
    }
Packit Service 51e54d
  else
Packit Service 51e54d
    {
Packit Service 51e54d
      print $STREAM <
Packit Service 51e54d
Usage: $ME [OPTIONS] [ARGS]
Packit Service 51e54d
Packit Service 51e54d
Convert git log output to ChangeLog format.  If present, any ARGS
Packit Service 51e54d
are passed to "git log".  To avoid ARGS being parsed as options to
Packit Service 51e54d
$ME, they may be preceded by '--'.
Packit Service 51e54d
Packit Service 51e54d
OPTIONS:
Packit Service 51e54d
Packit Service 51e54d
   --amend=FILE FILE maps from an SHA1 to perl code (i.e., s/old/new/) that
Packit Service 51e54d
                  makes a change to SHA1's commit log text or metadata.
Packit Service 51e54d
   --append-dot append a dot to the first line of each commit message if
Packit Service 51e54d
                  there is no other punctuation or blank at the end.
Packit Service 51e54d
   --no-cluster never cluster commit messages under the same date/author
Packit Service 51e54d
                  header; the default is to cluster adjacent commit messages
Packit Service 51e54d
                  if their headers are the same and neither commit message
Packit Service 51e54d
                  contains multiple paragraphs.
Packit Service 51e54d
   --srcdir=DIR the root of the source tree, from which the .git/
Packit Service 51e54d
                  directory can be derived.
Packit Service 51e54d
   --since=DATE convert only the logs since DATE;
Packit Service 51e54d
                  the default is to convert all log entries.
Packit Service 51e54d
   --format=FMT set format string for commit subject and body;
Packit Service 51e54d
                  see 'man git-log' for the list of format metacharacters;
Packit Service 51e54d
                  the default is '%s%n%b%n'
Packit Service 51e54d
   --strip-tab  remove one additional leading TAB from commit message lines.
Packit Service 51e54d
   --strip-cherry-pick  remove data inserted by "git cherry-pick";
Packit Service 51e54d
                  this includes the "cherry picked from commit ..." line,
Packit Service 51e54d
                  and the possible final "Conflicts:" paragraph.
Packit Service 51e54d
   --help       display this help and exit
Packit Service 51e54d
   --version    output version information and exit
Packit Service 51e54d
Packit Service 51e54d
EXAMPLE:
Packit Service 51e54d
Packit Service 51e54d
  $ME --since=2008-01-01 > ChangeLog
Packit Service 51e54d
  $ME -- -n 5 foo > last-5-commits-to-branch-foo
Packit Service 51e54d
Packit Service 51e54d
SPECIAL SYNTAX:
Packit Service 51e54d
Packit Service 51e54d
The following types of strings are interpreted specially when they appear
Packit Service 51e54d
at the beginning of a log message line.  They are not copied to the output.
Packit Service 51e54d
Packit Service 51e54d
  Copyright-paperwork-exempt: Yes
Packit Service 51e54d
    Append the "(tiny change)" notation to the usual "date name email"
Packit Service 51e54d
    ChangeLog header to mark a change that does not require a copyright
Packit Service 51e54d
    assignment.
Packit Service 51e54d
  Co-authored-by: Joe User <user\@example.com>
Packit Service 51e54d
    List the specified name and email address on a second
Packit Service 51e54d
    ChangeLog header, denoting a co-author.
Packit Service 51e54d
  Signed-off-by: Joe User <user\@example.com>
Packit Service 51e54d
    These lines are simply elided.
Packit Service 51e54d
Packit Service 51e54d
In a FILE specified via --amend, comment lines (starting with "#") are ignored.
Packit Service 51e54d
FILE must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1 (alone on
Packit Service 51e54d
a line) referring to a commit in the current project, and CODE refers to one
Packit Service 51e54d
or more consecutive lines of Perl code.  Pairs must be separated by one or
Packit Service 51e54d
more blank line.
Packit Service 51e54d
Packit Service 51e54d
Here is sample input for use with --amend=FILE, from coreutils:
Packit Service 51e54d
Packit Service 51e54d
3a169f4c5d9159283548178668d2fae6fced3030
Packit Service 51e54d
# fix typo in title:
Packit Service 51e54d
s/all tile types/all file types/
Packit Service 51e54d
Packit Service 51e54d
1379ed974f1fa39b12e2ffab18b3f7a607082202
Packit Service 51e54d
# Due to a bug in vc-dwim, I mis-attributed a patch by Paul to myself.
Packit Service 51e54d
# Change the author to be Paul.  Note the escaped "@":
Packit Service 51e54d
s,Jim .*>,Paul Eggert <eggert\\\@cs.ucla.edu>,
Packit Service 51e54d
Packit Service 51e54d
EOF
Packit Service 51e54d
    }
Packit Service 51e54d
  exit $exit_code;
Packit Service 51e54d
}
Packit Service 51e54d
Packit Service 51e54d
# If the string $S is a well-behaved file name, simply return it.
Packit Service 51e54d
# If it contains white space, quotes, etc., quote it, and return the new string.
Packit Service 51e54d
sub shell_quote($)
Packit Service 51e54d
{
Packit Service 51e54d
  my ($s) = @_;
Packit Service 51e54d
  if ($s =~ m![^\w+/.,-]!)
Packit Service 51e54d
    {
Packit Service 51e54d
      # Convert each single quote to '\''
Packit Service 51e54d
      $s =~ s/\'/\'\\\'\'/g;
Packit Service 51e54d
      # Then single quote the string.
Packit Service 51e54d
      $s = "'$s'";
Packit Service 51e54d
    }
Packit Service 51e54d
  return $s;
Packit Service 51e54d
}
Packit Service 51e54d
Packit Service 51e54d
sub quoted_cmd(@)
Packit Service 51e54d
{
Packit Service 51e54d
  return join (' ', map {shell_quote $_} @_);
Packit Service 51e54d
}
Packit Service 51e54d
Packit Service 51e54d
# Parse file F.
Packit Service 51e54d
# Comment lines (starting with "#") are ignored.
Packit Service 51e54d
# F must consist of <SHA,CODE+> pairs where SHA is a 40-byte SHA1
Packit Service 51e54d
# (alone on a line) referring to a commit in the current project, and
Packit Service 51e54d
# CODE refers to one or more consecutive lines of Perl code.
Packit Service 51e54d
# Pairs must be separated by one or more blank line.
Packit Service 51e54d
sub parse_amend_file($)
Packit Service 51e54d
{
Packit Service 51e54d
  my ($f) = @_;
Packit Service 51e54d
Packit Service 51e54d
  open F, '<', $f
Packit Service 51e54d
    or die "$ME: $f: failed to open for reading: $!\n";
Packit Service 51e54d
Packit Service 51e54d
  my $fail;
Packit Service 51e54d
  my $h = {};
Packit Service 51e54d
  my $in_code = 0;
Packit Service 51e54d
  my $sha;
Packit Service 51e54d
  while (defined (my $line = <F>))
Packit Service 51e54d
    {
Packit Service 51e54d
      $line =~ /^\#/
Packit Service 51e54d
        and next;
Packit Service 51e54d
      chomp $line;
Packit Service 51e54d
      $line eq ''
Packit Service 51e54d
        and $in_code = 0, next;
Packit Service 51e54d
Packit Service 51e54d
      if (!$in_code)
Packit Service 51e54d
        {
Packit Service 51e54d
          $line =~ /^([0-9a-fA-F]{40})$/
Packit Service 51e54d
            or (warn "$ME: $f:$.: invalid line; expected an SHA1\n"),
Packit Service 51e54d
              $fail = 1, next;
Packit Service 51e54d
          $sha = lc $1;
Packit Service 51e54d
          $in_code = 1;
Packit Service 51e54d
          exists $h->{$sha}
Packit Service 51e54d
            and (warn "$ME: $f:$.: duplicate SHA1\n"),
Packit Service 51e54d
              $fail = 1, next;
Packit Service 51e54d
        }
Packit Service 51e54d
      else
Packit Service 51e54d
        {
Packit Service 51e54d
          $h->{$sha} ||= '';
Packit Service 51e54d
          $h->{$sha} .= "$line\n";
Packit Service 51e54d
        }
Packit Service 51e54d
    }
Packit Service 51e54d
  close F;
Packit Service 51e54d
Packit Service 51e54d
  $fail
Packit Service 51e54d
    and exit 1;
Packit Service 51e54d
Packit Service 51e54d
  return $h;
Packit Service 51e54d
}
Packit Service 51e54d
Packit Service 51e54d
# git_dir_option $SRCDIR
Packit Service 51e54d
#
Packit Service 51e54d
# From $SRCDIR, the --git-dir option to pass to git (none if $SRCDIR
Packit Service 51e54d
# is undef).  Return as a list (0 or 1 element).
Packit Service 51e54d
sub git_dir_option($)
Packit Service 51e54d
{
Packit Service 51e54d
  my ($srcdir) = @_;
Packit Service 51e54d
  my @res = ();
Packit Service 51e54d
  if (defined $srcdir)
Packit Service 51e54d
    {
Packit Service 51e54d
      my $qdir = shell_quote $srcdir;
Packit Service 51e54d
      my $cmd = "cd $qdir && git rev-parse --show-toplevel";
Packit Service 51e54d
      my $qcmd = shell_quote $cmd;
Packit Service 51e54d
      my $git_dir = qx($cmd);
Packit Service 51e54d
      defined $git_dir
Packit Service 51e54d
        or die "$ME: cannot run $qcmd: $!\n";
Packit Service 51e54d
      $? == 0
Packit Service 51e54d
        or die "$ME: $qcmd had unexpected exit code or signal ($?)\n";
Packit Service 51e54d
      chomp $git_dir;
Packit Service 51e54d
      push @res, "--git-dir=$git_dir/.git";
Packit Service 51e54d
    }
Packit Service 51e54d
  @res;
Packit Service 51e54d
}
Packit Service 51e54d
Packit Service 51e54d
{
Packit Service 51e54d
  my $since_date;
Packit Service 51e54d
  my $format_string = '%s%n%b%n';
Packit Service 51e54d
  my $amend_file;
Packit Service 51e54d
  my $append_dot = 0;
Packit Service 51e54d
  my $cluster = 1;
Packit Service 51e54d
  my $strip_tab = 0;
Packit Service 51e54d
  my $strip_cherry_pick = 0;
Packit Service 51e54d
  my $srcdir;
Packit Service 51e54d
  GetOptions
Packit Service 51e54d
    (
Packit Service 51e54d
     help => sub { usage 0 },
Packit Service 51e54d
     version => sub { print "$ME version $VERSION\n"; exit },
Packit Service 51e54d
     'since=s' => \$since_date,
Packit Service 51e54d
     'format=s' => \$format_string,
Packit Service 51e54d
     'amend=s' => \$amend_file,
Packit Service 51e54d
     'append-dot' => \$append_dot,
Packit Service 51e54d
     'cluster!' => \$cluster,
Packit Service 51e54d
     'strip-tab' => \$strip_tab,
Packit Service 51e54d
     'strip-cherry-pick' => \$strip_cherry_pick,
Packit Service 51e54d
     'srcdir=s' => \$srcdir,
Packit Service 51e54d
    ) or usage 1;
Packit Service 51e54d
Packit Service 51e54d
  defined $since_date
Packit Service 51e54d
    and unshift @ARGV, "--since=$since_date";
Packit Service 51e54d
Packit Service 51e54d
  # This is a hash that maps an SHA1 to perl code (i.e., s/old/new/)
Packit Service 51e54d
  # that makes a correction in the log or attribution of that commit.
Packit Service 51e54d
  my $amend_code = defined $amend_file ? parse_amend_file $amend_file : {};
Packit Service 51e54d
Packit Service 51e54d
  my @cmd = ('git',
Packit Service 51e54d
             git_dir_option $srcdir,
Packit Service 51e54d
             qw(log --log-size),
Packit Service 51e54d
             '--pretty=format:%H:%ct  %an  <%ae>%n%n'.$format_string, @ARGV);
Packit Service 51e54d
  open PIPE, '-|', @cmd
Packit Service 51e54d
    or die ("$ME: failed to run '". quoted_cmd (@cmd) ."': $!\n"
Packit Service 51e54d
            . "(Is your Git too old?  Version 1.5.1 or later is required.)\n");
Packit Service 51e54d
Packit Service 51e54d
  my $prev_multi_paragraph;
Packit Service 51e54d
  my $prev_date_line = '';
Packit Service 51e54d
  my @prev_coauthors = ();
Packit Service 51e54d
  while (1)
Packit Service 51e54d
    {
Packit Service 51e54d
      defined (my $in = <PIPE>)
Packit Service 51e54d
        or last;
Packit Service 51e54d
      $in =~ /^log size (\d+)$/
Packit Service 51e54d
        or die "$ME:$.: Invalid line (expected log size):\n$in";
Packit Service 51e54d
      my $log_nbytes = $1;
Packit Service 51e54d
Packit Service 51e54d
      my $log;
Packit Service 51e54d
      my $n_read = read PIPE, $log, $log_nbytes;
Packit Service 51e54d
      $n_read == $log_nbytes
Packit Service 51e54d
        or die "$ME:$.: unexpected EOF\n";
Packit Service 51e54d
Packit Service 51e54d
      # Extract leading hash.
Packit Service 51e54d
      my ($sha, $rest) = split ':', $log, 2;
Packit Service 51e54d
      defined $sha
Packit Service 51e54d
        or die "$ME:$.: malformed log entry\n";
Packit Service 51e54d
      $sha =~ /^[0-9a-fA-F]{40}$/
Packit Service 51e54d
        or die "$ME:$.: invalid SHA1: $sha\n";
Packit Service 51e54d
Packit Service 51e54d
      # If this commit's log requires any transformation, do it now.
Packit Service 51e54d
      my $code = $amend_code->{$sha};
Packit Service 51e54d
      if (defined $code)
Packit Service 51e54d
        {
Packit Service 51e54d
          eval 'use Safe';
Packit Service 51e54d
          my $s = new Safe;
Packit Service 51e54d
          # Put the unpreprocessed entry into "$_".
Packit Service 51e54d
          $_ = $rest;
Packit Service 51e54d
Packit Service 51e54d
          # Let $code operate on it, safely.
Packit Service 51e54d
          my $r = $s->reval("$code")
Packit Service 51e54d
            or die "$ME:$.:$sha: failed to eval \"$code\":\n$@\n";
Packit Service 51e54d
Packit Service 51e54d
          # Note that we've used this entry.
Packit Service 51e54d
          delete $amend_code->{$sha};
Packit Service 51e54d
Packit Service 51e54d
          # Update $rest upon success.
Packit Service 51e54d
          $rest = $_;
Packit Service 51e54d
        }
Packit Service 51e54d
Packit Service 51e54d
      # Remove lines inserted by "git cherry-pick".
Packit Service 51e54d
      if ($strip_cherry_pick)
Packit Service 51e54d
        {
Packit Service 51e54d
          $rest =~ s/^\s*Conflicts:\n.*//sm;
Packit Service 51e54d
          $rest =~ s/^\s*\(cherry picked from commit [\da-f]+\)\n//m;
Packit Service 51e54d
        }
Packit Service 51e54d
Packit Service 51e54d
      my @line = split "\n", $rest;
Packit Service 51e54d
      my $author_line = shift @line;
Packit Service 51e54d
      defined $author_line
Packit Service 51e54d
        or die "$ME:$.: unexpected EOF\n";
Packit Service 51e54d
      $author_line =~ /^(\d+)  (.*>)$/
Packit Service 51e54d
        or die "$ME:$.: Invalid line "
Packit Service 51e54d
          . "(expected date/author/email):\n$author_line\n";
Packit Service 51e54d
Packit Service 51e54d
      # Format 'Copyright-paperwork-exempt: Yes' as a standard ChangeLog
Packit Service 51e54d
      # `(tiny change)' annotation.
Packit Service 51e54d
      my $tiny = (grep (/^Copyright-paperwork-exempt:\s+[Yy]es$/, @line)
Packit Service 51e54d
                  ? '  (tiny change)' : '');
Packit Service 51e54d
Packit Service 51e54d
      my $date_line = sprintf "%s  %s$tiny\n",
Packit Service 51e54d
        strftime ("%F", localtime ($1)), $2;
Packit Service 51e54d
Packit Service 51e54d
      my @coauthors = grep /^Co-authored-by:.*$/, @line;
Packit Service 51e54d
      # Omit meta-data lines we've already interpreted.
Packit Service 51e54d
      @line = grep !/^(?:Signed-off-by:[ ].*>$
Packit Service 51e54d
                       |Co-authored-by:[ ]
Packit Service 51e54d
                       |Copyright-paperwork-exempt:[ ]
Packit Service 51e54d
                       )/x, @line;
Packit Service 51e54d
Packit Service 51e54d
      # Remove leading and trailing blank lines.
Packit Service 51e54d
      if (@line)
Packit Service 51e54d
        {
Packit Service 51e54d
          while ($line[0] =~ /^\s*$/) { shift @line; }
Packit Service 51e54d
          while ($line[$#line] =~ /^\s*$/) { pop @line; }
Packit Service 51e54d
        }
Packit Service 51e54d
Packit Service 51e54d
      # Record whether there are two or more paragraphs.
Packit Service 51e54d
      my $multi_paragraph = grep /^\s*$/, @line;
Packit Service 51e54d
Packit Service 51e54d
      # Format 'Co-authored-by: A U Thor <email@example.com>' lines in
Packit Service 51e54d
      # standard multi-author ChangeLog format.
Packit Service 51e54d
      for (@coauthors)
Packit Service 51e54d
        {
Packit Service 51e54d
          s/^Co-authored-by:\s*/\t    /;
Packit Service 51e54d
          s/\s*</  </;
Packit Service 51e54d
Packit Service 51e54d
          /<.*?@.*\..*>/
Packit Service 51e54d
            or warn "$ME: warning: missing email address for "
Packit Service 51e54d
              . substr ($_, 5) . "\n";
Packit Service 51e54d
        }
Packit Service 51e54d
Packit Service 51e54d
      # If clustering of commit messages has been disabled, if this header
Packit Service 51e54d
      # would be different from the previous date/name/email/coauthors header,
Packit Service 51e54d
      # or if this or the previous entry consists of two or more paragraphs,
Packit Service 51e54d
      # then print the header.
Packit Service 51e54d
      if ( ! $cluster
Packit Service 51e54d
          || $date_line ne $prev_date_line
Packit Service 51e54d
          || "@coauthors" ne "@prev_coauthors"
Packit Service 51e54d
          || $multi_paragraph
Packit Service 51e54d
          || $prev_multi_paragraph)
Packit Service 51e54d
        {
Packit Service 51e54d
          $prev_date_line eq ''
Packit Service 51e54d
            or print "\n";
Packit Service 51e54d
          print $date_line;
Packit Service 51e54d
          @coauthors
Packit Service 51e54d
            and print join ("\n", @coauthors), "\n";
Packit Service 51e54d
        }
Packit Service 51e54d
      $prev_date_line = $date_line;
Packit Service 51e54d
      @prev_coauthors = @coauthors;
Packit Service 51e54d
      $prev_multi_paragraph = $multi_paragraph;
Packit Service 51e54d
Packit Service 51e54d
      # If there were any lines
Packit Service 51e54d
      if (@line == 0)
Packit Service 51e54d
        {
Packit Service 51e54d
          warn "$ME: warning: empty commit message:\n  $date_line\n";
Packit Service 51e54d
        }
Packit Service 51e54d
      else
Packit Service 51e54d
        {
Packit Service 51e54d
          if ($append_dot)
Packit Service 51e54d
            {
Packit Service 51e54d
              # If the first line of the message has enough room, then
Packit Service 51e54d
              if (length $line[0] < 72)
Packit Service 51e54d
                {
Packit Service 51e54d
                  # append a dot if there is no other punctuation or blank
Packit Service 51e54d
                  # at the end.
Packit Service 51e54d
                  $line[0] =~ /[[:punct:]\s]$/
Packit Service 51e54d
                    or $line[0] .= '.';
Packit Service 51e54d
                }
Packit Service 51e54d
            }
Packit Service 51e54d
Packit Service 51e54d
          # Remove one additional leading TAB from each line.
Packit Service 51e54d
          $strip_tab
Packit Service 51e54d
            and map { s/^\t// } @line;
Packit Service 51e54d
Packit Service 51e54d
          # Prefix each non-empty line with a TAB.
Packit Service 51e54d
          @line = map { length $_ ? "\t$_" : '' } @line;
Packit Service 51e54d
Packit Service 51e54d
          print "\n", join ("\n", @line), "\n";
Packit Service 51e54d
        }
Packit Service 51e54d
Packit Service 51e54d
      defined ($in = <PIPE>)
Packit Service 51e54d
        or last;
Packit Service 51e54d
      $in ne "\n"
Packit Service 51e54d
        and die "$ME:$.: unexpected line:\n$in";
Packit Service 51e54d
    }
Packit Service 51e54d
Packit Service 51e54d
  close PIPE
Packit Service 51e54d
    or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
Packit Service 51e54d
  # FIXME-someday: include $PROCESS_STATUS in the diagnostic
Packit Service 51e54d
Packit Service 51e54d
  # Complain about any unused entry in the --amend=F specified file.
Packit Service 51e54d
  my $fail = 0;
Packit Service 51e54d
  foreach my $sha (keys %$amend_code)
Packit Service 51e54d
    {
Packit Service 51e54d
      warn "$ME:$amend_file: unused entry: $sha\n";
Packit Service 51e54d
      $fail = 1;
Packit Service 51e54d
    }
Packit Service 51e54d
Packit Service 51e54d
  exit $fail;
Packit Service 51e54d
}
Packit Service 51e54d
Packit Service 51e54d
# Local Variables:
Packit Service 51e54d
# mode: perl
Packit Service 51e54d
# indent-tabs-mode: nil
Packit Service 51e54d
# eval: (add-hook 'write-file-hooks 'time-stamp)
Packit Service 51e54d
# time-stamp-start: "my $VERSION = '"
Packit Service 51e54d
# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
Packit Service 51e54d
# time-stamp-time-zone: "UTC"
Packit Service 51e54d
# time-stamp-end: "'; # UTC"
Packit Service 51e54d
# End: