make_emacs_changelog 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #!/usr/bin/perl
  2. $commitrange = shift @ARGV;
  3. if (!$commitrange) {
  4. print STDERR "Enter commitrange: ";
  5. $commitrange = <>;
  6. $commitrange =~ s/\s*(.*?)\s+/$1/;
  7. }
  8. $syncdate = shift @ARGV;
  9. if (!$syncdate) {
  10. print STDERR "Enter syncdate YYYY-MM-DD: ";
  11. $syncdate = <>;
  12. $syncdate =~ s/\s*(.*?)\s+/$1/;
  13. }
  14. $kind = shift @ARGV;
  15. if (!$kind) {
  16. print STDERR 'Enter kind ("lisp" or "texi" or "card" or press RET): ';
  17. $kind = <>;
  18. $kind =~ s/\s*(.*?)\s+/$1/;
  19. $kind =~ s/"(.*?)"/$1/;
  20. }
  21. if ($kind ne "lisp" and $kind ne "texi" and $kind ne "card"
  22. and $kind ne "") {
  23. die "Invalid Changelog kind";
  24. }
  25. # Run git log to get the commits the messages
  26. open IN,"git log $commitrange|";
  27. undef $/;
  28. $log = <IN>;
  29. @commits = split(/^(?=commit)/m,$log);
  30. for $i (0..$#commits) {
  31. $entry = ""; $tiny = "";
  32. $commit = $commits[$i];
  33. $author = $1 if $commit=~/^Author: ([^\n]+)/m;
  34. $date = $1 if $commit=~/^Date: ([^\n]+)/m;
  35. $entry = $1 if $commit=~/^([ \t]*\* [^\f]*?)(\n[ \t]*\n([^*]|\Z)|\Z)/m;
  36. $tiny = " (tiny change)" if $commit =~ /TINYCHANGE/;
  37. # split author into name and address
  38. if ($author =~ /(.*?)\s+(<.*?>)/) {
  39. $name = $1;
  40. $address = $2;
  41. } else {
  42. warn "No name/address";
  43. next;
  44. }
  45. if ($entry) {
  46. # Fix the path when directories have been omitted
  47. $entry =~ s/^([ \t]*\* )([-a-zA-Z]+\.el)/$1lisp\/$2/mg;
  48. $entry =~ s/^([ \t]*\* )(org[a-z]*\.texi?)/$1doc\/$2/mg;
  49. # remove stuff which is not for this output
  50. if ($kind =~ /\S/) {
  51. remove_parts("contrib/","testing/","xemacs/");
  52. remove_parts("Makefile","README");
  53. }
  54. if ($kind eq "lisp") { remove_parts("doc/") }
  55. if ($kind eq "texi") { remove_parts("lisp/","doc/orgcard","doc/orgguide") }
  56. if ($kind eq "card") { remove_parts("lisp/","doc/org\\.","doc/orgguide") }
  57. # indent each line by 1 TAB
  58. $entry =~ s/^[ \t]*/\t/gm;
  59. # Add empty lines if there are several files in there
  60. $entry =~ s/(\n[ \t]+\* )/\n$1/g;
  61. # remove blocks of more than one empty line
  62. while ($entry =~s/\n[ \t]*\n[ \t]*\n/\n/g) {};
  63. # remove/replace parts of the path
  64. $entry =~ s/^([ \t]+\* )lisp\//$1/mg;
  65. $entry =~ s/^([ \t]+\* )doc\/orgcard/$1 refcards\/orgcard/mg;
  66. $entry =~ s/^([ \t]+\* )doc\//$1misc\//mg;
  67. # remove empty space at beginning and end
  68. $entry =~ s/\A\s*/\t/;
  69. $entry =~ s/\s*\Z/\n/;
  70. # If there is anything left in the entry, print it
  71. if ($entry =~ /\S/) {
  72. print "$syncdate $name $address$tiny\n\n$entry\n";
  73. }
  74. }
  75. }
  76. sub remove_parts {
  77. foreach $path (@_) {
  78. $re = "^[ \t]*\\*\\s+" . $path . "[^\\000]*?(?=^[ \\t]*\\*|\\Z)";
  79. $entry =~ s/$re/\n$1/mg;
  80. }
  81. }