📄 cvs2cl.pl
字号:
$suppress_line_start_match = 1; last; } else { $idx--; } } if ($idx == 0) { # We bottomed out because the line is longer than the # available space. But that could be because the space is # small, or because the line is longer than even the maximum # possible space. Handle both cases below. if ($length_remaining == ($max_line_length - (length ($user_indent)))) { # The line is simply too long -- there is no hope of ever # breaking it nicely, so just insert it verbatim, with # appropriate padding. $this_line = "\n${left_pad_str}${this_line}"; } else { # Can't break it here, but may be able to on the next round... unshift (@lines, $this_line); $length_remaining = $max_line_length - (length ($user_indent)); $this_line = "\n${left_pad_str}"; } } } else # $this_len < $length_remaining, so tack on what we can. { # Leave a note for the next iteration. $length_remaining = $length_remaining - $this_len; if ($this_line =~ /\.$/) { $this_line .= " "; $length_remaining -= 2; } else # not a sentence end { $this_line .= " "; $length_remaining -= 1; } } # Unconditionally indicate that loop has run at least once. $first_time = 0; $wrapped_text .= "${user_indent}${this_line}"; } # One last bit of padding. $wrapped_text .= "\n"; return $wrapped_text;}sub xml_escape (){ my $txt = shift; $txt =~ s/&/&/g; $txt =~ s/</</g; $txt =~ s/>/>/g; return $txt;}sub maybe_read_user_map_file (){ my %expansions; if ($User_Map_File) { open (MAPFILE, "<$User_Map_File") or die ("Unable to open $User_Map_File ($!)"); while (<MAPFILE>) { next if /^\s*#/; # Skip comment lines. next if not /:/; # Skip lines without colons. # It is now safe to split on ':'. my ($username, $expansion) = split ':'; chomp $expansion; $expansion =~ s/^'(.*)'$/$1/; $expansion =~ s/^"(.*)"$/$1/; # If it looks like the expansion has a real name already, then # we toss the username we got from CVS log. Otherwise, keep # it to use in combination with the email address. if ($expansion =~ /^\s*<{0,1}\S+@.*/) { # Also, add angle brackets if none present if (! ($expansion =~ /<\S+@\S+>/)) { $expansions{$username} = "$username <$expansion>"; } else { $expansions{$username} = "$username $expansion"; } } else { $expansions{$username} = $expansion; } } # fi ($User_Map_File) close (MAPFILE); } if (defined $User_Passwd_File) { if ( ! defined $Mail_Domain ) { if ( -e MAILNAME ) { chomp($Mail_Domain = slurp_file(MAILNAME)); } else { MAILDOMAIN_CMD: for ([qw(hostname -d)], 'dnsdomainname', 'domainname') { my ($text, $exit, $sig, $core) = run_ext($_); if ( $exit == 0 && $sig == 0 && $core == 0 ) { chomp $text; if ( length $text ) { $Mail_Domain = $text; last MAILDOMAIN_CMD; } } } } } die "No mail domain found\n" unless defined $Mail_Domain; open (MAPFILE, "<$User_Passwd_File") or die ("Unable to open $User_Passwd_File ($!)"); while (<MAPFILE>) { # all lines are valid my ($username, $pw, $uid, $gid, $gecos, $homedir, $shell) = split ':'; my $expansion = ''; ($expansion) = split (',', $gecos) if defined $gecos && length $gecos; $expansions{$username} = "$expansion <$username\@$Mail_Domain>"; } close (MAPFILE); } return %expansions;}sub parse_options (){ # Check this internally before setting the global variable. my $output_file; # If this gets set, we encountered unknown options and will exit at # the end of this subroutine. my $exit_with_admonishment = 0; while (my $arg = shift (@ARGV)) { if ($arg =~ /^-h$|^-help$|^--help$|^--usage$|^-?$/) { $Print_Usage = 1; } elsif ($arg =~ /^--delta$/) { my $narg = shift(@ARGV) || die "$arg needs argument.\n"; if ($narg =~ /^([A-Za-z][A-Za-z0-9_\-]*):([A-Za-z][A-Za-z0-9_\-]*)$/) { $Delta_From = $1; $Delta_To = $2; $Delta_Mode = 1; } else { die "--delta FROM_TAG:TO_TAG is what you meant to say.\n"; } } elsif ($arg =~ /^--debug$/) { # unadvertised option, heh $Debug = 1; } elsif ($arg =~ /^--version$/) { $Print_Version = 1; } elsif ($arg =~ /^-g$|^--global-opts$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; # Don't assume CVS is called "cvs" on the user's system: $Log_Source_Command =~ s/(^\S*)/$1 $narg/; } elsif ($arg =~ /^-l$|^--log-opts$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $Log_Source_Command .= " $narg"; } elsif ($arg =~ /^-f$|^--file$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $output_file = $narg; } elsif ($arg =~ /^--accum$/) { $Cumulative = 1; } elsif ($arg =~ /^--update$/) { $Update = 1; } elsif ($arg =~ /^--fsf$/) { $FSF_Style = 1; } elsif ($arg =~ /^--FSF$/) { $Show_Times = 0; $Common_Dir = 0; } elsif ($arg =~ /^--rcs/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $RCS_Root = $narg; $RCS_Mode = 1; } elsif ($arg =~ /^-U$|^--usermap$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $User_Map_File = $narg; } elsif ($arg =~ /^--gecos$/) { $Gecos = 1; } elsif ($arg =~ /^--domain$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $Domain = $narg; } elsif ($arg =~ /^--passwd$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $User_Passwd_File = $narg; } elsif ($arg =~ /^--mailname$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $Mail_Domain = $narg; } elsif ($arg =~ /^-W$|^--window$/) { defined(my $narg = shift (@ARGV)) || die "$arg needs argument.\n"; $Max_Checkin_Duration = $narg; } elsif ($arg =~ /^--chrono$/) { $Chronological_Order = 1; } elsif ($arg =~ /^-I$|^--ignore$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; push (@Ignore_Files, $narg); } elsif ($arg =~ /^-C$|^--case-insensitive$/) { $Case_Insensitive = 1; } elsif ($arg =~ /^-R$|^--regexp$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $Regexp_Gate = $narg; } elsif ($arg =~ /^--stdout$/) { $Output_To_Stdout = 1; } elsif ($arg =~ /^--version$/) { $Print_Version = 1; } elsif ($arg =~ /^-d$|^--distributed$/) { $Distributed = 1; } elsif ($arg =~ /^-P$|^--prune$/) { $Prune_Empty_Msgs = 1; } elsif ($arg =~ /^-S$|^--separate-header$/) { $After_Header = "\n\n"; } elsif ($arg =~ /^--no-wrap$/) { $No_Wrap = 1; } elsif ($arg =~ /^--summary$/) { $Summary = 1; $After_Header = "\n\n"; # Summary implies --separate-header } elsif ($arg =~ /^--gmt$|^--utc$/) { $UTC_Times = 1; } elsif ($arg =~ /^-w$|^--day-of-week$/) { $Show_Day_Of_Week = 1; } elsif ($arg =~ /^--no-times$/) { $Show_Times = 0; } elsif ($arg =~ /^-r$|^--revisions$/) { $Show_Revisions = 1; } elsif ($arg =~ /^--show-dead$/) { $Show_Dead = 1; } elsif ($arg =~ /^-t$|^--tags$/) { $Show_Tags = 1; } elsif ($arg =~ /^-T$|^--tagdates$/) { $Show_Tag_Dates = 1; } elsif ($arg =~ /^-b$|^--branches$/) { $Show_Branches = 1; } elsif ($arg =~ /^-F$|^--follow$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; push (@Follow_Branches, $narg); } elsif ($arg =~ /^--stdin$/) { $Input_From_Stdin = 1; } elsif ($arg =~ /^--header$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $ChangeLog_Header = &slurp_file ($narg); if (! defined ($ChangeLog_Header)) { $ChangeLog_Header = ""; } } elsif ($arg =~ /^--xml-encoding$/) { my $narg = shift (@ARGV) || die "$arg needs argument.\n"; $XML_Encoding = $narg ; } elsif ($arg =~ /^--xml$/) { $XML_Output = 1; } elsif ($arg =~ /^--hide-filenames$/) { $Hide_Filenames = 1; $After_Header = ""; } elsif ($arg =~ /^--no-common-dir$/) { $Common_Dir = 0; } elsif ($arg =~ /^--ignore-tag$/ ) { die "$arg needs argument.\n" unless @ARGV; $ignore_tags{shift @ARGV} = 1; } elsif ($arg =~ /^--show-tag$/ ) { die "$arg needs argument.\n" unless @ARGV; $show_tags{shift @ARGV} = 1; } elsif ( lc ($arg) eq '--test-code' ) { # Deliberately undocumented. This is not a public interface, # and may change/disappear at any time. die "$arg needs argument.\n" unless @ARGV; $TestCode = shift @ARGV; } elsif ($arg =~ /^--no-ancestors$/) { $No_Ancestors = 1; } else { # Just add a filename as argument to the log command $Log_Source_Command .= " '$arg'"; } } ## Check for contradictions... if ($Output_To_Stdout && $Distributed) { print STDERR "cannot pass both --stdout and --distributed\n"; $exit_with_admonishment = 1; } if ($Output_To_Stdout && $output_file) { print STDERR "cannot pass both --stdout and --file\n"; $exit_with_admonishment = 1; } if ($XML_Output && $Cumulative) { print STDERR "cannot pass both --xml and --accum\n"; $exit_with_admonishment = 1; } # Or if any other error message has already been printed out, we # just leave now: if ($exit_with_admonishment) { &usage (); exit (1); } elsif ($Print_Usage) { &usage (); exit (0); } elsif ($Print_Version) { &version (); exit (0); } ## Else no problems, so proceed. if ($output_file) { $Log_File_Name = $output_file; }}sub slurp_file (){ my $filename = shift || die ("no filename passed to slurp_file()"); my $retstr; open (SLURPEE, "<${filename}") or die ("unable to open $filename ($!)"); my $saved_sep = $/; undef $/; $retstr = <SLURPEE>; $/ = $saved_sep; close (SLURPEE); return $retstr;}sub debug (){ if ($Debug) { my $msg = shift; print STDERR $msg; }}sub version (){ print "cvs2cl.pl version ${VERSION}; distributed under the GNU GPL.\n";}sub usage (){ &version (); print <<'END_OF_INFO';Generate GNU-style ChangeLogs in CVS working copies.Notes about the output format(s): The default output of cvs2cl.pl is designed to be
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -