The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
Build.PL 3340
Changes 043
MANIFEST 17
META.yml 1718
Makefile.PL 390
README 11
dist.ini 391
lib/Dist/Zilla/Plugin/Git/Check.pm 2527
lib/Dist/Zilla/Plugin/Git/Commit.pm 23101
lib/Dist/Zilla/Plugin/Git/Push.pm 924
lib/Dist/Zilla/Plugin/Git/Tag.pm 1165
lib/Dist/Zilla/Plugin/Git.pm 36
lib/Dist/Zilla/PluginBundle/Git.pm 1121
lib/Dist/Zilla/Role/Git/DirtyFiles.pm 0116
t/00-compile.t 1218
t/1-check.t 76
t/2-commit-ws.t 058
t/2-commit.t 78
t/3-tag.t 714
t/4-push-multi.t 070
t/4-push.t 1616
t/author-critic.t 03
t/check/dist.ini 01
t/commit/dist.ini 01
t/commit-ws/Changes 021
t/commit-ws/dist.ini 017
t/push/dist.ini 01
t/push-multi/Changes 09
t/push-multi/dist.ini 016
t/tag/dist.ini 01
30 files changed (This is a version diff) 261730
@@ -2,39 +2,46 @@
 use strict;
 use warnings;
 
-use Module::Build;
+use Module::Build 0.3601;
 
-my $build = Module::Build->new(
-  module_name   => 'Dist::Zilla::Plugin::Git',
-  license       => 'perl',
-  dist_abstract => "update\ your\ git\ repository\ after\ release",
-  dist_name     => "Dist\-Zilla\-Plugin\-Git",
-  dist_author   => [
-"Jerome\ Quelin",
-  ],
-  requires      => {
-    "MooseX::Has::Sugar" => '0',
-    "MooseX::Types::Moose" => '0',
-    "Dist::Zilla::Role::PluginBundle" => '0',
-    "Git::Wrapper" => '0',
-    "Dist::Zilla::Role::AfterRelease" => '0',
-    "File::Find" => '0',
-    "File::Path" => '2.07',
-    "File::Spec::Functions" => '0',
-    "Moose" => '0',
-    "English" => '0',
-    "Test::Exception" => '0',
-    "ExtUtils::MakeMaker" => '0',
-    "Moose::Autobox" => '0',
-    "perl" => '5.008',
-    "Test::More" => '0',
-    "File::Temp" => '0',
-    "Dist::Zilla" => '1.093250',
-    "Dist::Zilla::Role::BeforeRelease" => '0',
-    "String::Formatter" => '0',
-    "Cwd" => '0',
-  },
-  script_files => [ qw() ],
-);
+my %module_build_args = (
+                       'dist_abstract' => 'update your git repository after release',
+                       'script_files' => [],
+                       'license' => 'perl',
+                       'build_requires' => {},
+                       'dist_name' => 'Dist-Zilla-Plugin-Git',
+                       'dist_author' => [
+                                          'Jerome Quelin'
+                                        ],
+                       'module_name' => 'Dist::Zilla::Plugin::Git',
+                       'requires' => {
+                                       'MooseX::Types::Moose' => '0',
+                                       'MooseX::Has::Sugar' => '0',
+                                       'DateTime' => '0',
+                                       'Dist::Zilla::Role::PluginBundle' => '0',
+                                       'Class::MOP' => '0',
+                                       'Git::Wrapper' => '0',
+                                       'Dist::Zilla::Role::AfterRelease' => '0',
+                                       'File::Find' => '0',
+                                       'Moose' => '0',
+                                       'Moose::Role' => '0',
+                                       'English' => '0',
+                                       'Test::Exception' => '0',
+                                       'Moose::Autobox' => '0',
+                                       'Test::More' => '0',
+                                       'perl' => '5.008',
+                                       'Dist::Zilla' => '1.100660',
+                                       'File::Temp' => '0',
+                                       'Dist::Zilla::Role::BeforeRelease' => '0',
+                                       'Path::Class' => '0',
+                                       'String::Formatter' => '0',
+                                       'Cwd' => '0'
+                                     },
+                       'configure_requires' => {},
+                       'dist_version' => '1.100760'
+                     );
+
+
+my $build = Module::Build->new(%module_build_args);
 
 $build->create_build_script;
@@ -1,5 +1,48 @@
 Revision history for Dist::Zilla::Plugin::Git
 
+1.100760  2010-03-17 10:16:56 Europe/Paris
+ - add a BeforeRelease check in Tag to prevent re-releases (christopher madsen)
+ - Commit and Push now pass Git's output to log_debug (christopher madsen)
+
+1.100750  2010-03-16 16:25:56 Europe/Paris
+ - actually use commit_msg (christopher madsen)
+ - Push now logs before pushing (christopher madsen)
+
+1.100741  2010-03-15 18:48:31 Europe/Paris
+ - documentation fix for new push_to param
+
+1.100740  2010-03-15 17:28:12 Europe/Paris
+ - WARNING: parameter "filename" renamed to "changelog"
+ - let commit message include whitespace to next unindented line (david golden)
+ - set up remote tracking branch during push testing (david golden)
+ - remove unnecessary 'filename' arg from Push (david golden)
+ - add 'push_to' argument to Push for multi-repo pushes (david golden)
+ - give back user possibility to create lightweight tag, default remains
+   annotated tags (christopher madsen)
+ - allow user to change commit message (christopher madsen)
+ - allow user to specify files allowed to be dirty for check & commit (christopher madsen)
+ - refactored allow_dirty in dz:role:git:dirtyfiles (christopher madsen)
+
+1.100690  2010-03-10 13:20:37 Europe/Paris
+ - fix tests to work even when no global git config exists
+ - refactored commit message generation (christopher madsen)
+
+1.100681  2010-03-09 17:26:14 Europe/Paris
+ - bumping minimum dzil version requirement
+
+1.100680  2010-03-09 17:07:45 Europe/Paris
+ - using annotated tags instead of lightweight tags (rt#55352)
+ - minor pod update
+
+1.100660  2010-03-07 13:41:39 Europe/Paris
+ - fix tests to work with git 1.7.0
+ - fix tests to work with current Dist::Zilla (Ricardo Signes)
+ - provide shorter plugin names to bundle contents (Ricardo Signes)
+
+1.100430  2010-02-12 13:11:39 Europe/Paris
+ - WARNING: no more makefile.pl supplied, only a build.pl
+ - using path::class in the tests
+
 1.093410  2009-12-07 09:13:07 Europe/Paris
  - require file::path 2.07 for remove_tree
 
@@ -3,7 +3,6 @@ Changes
 LICENSE
 MANIFEST
 META.yml
-Makefile.PL
 README
 dist.ini
 lib/Dist/Zilla/Plugin/Git.pm
@@ -12,17 +11,24 @@ lib/Dist/Zilla/Plugin/Git/Commit.pm
 lib/Dist/Zilla/Plugin/Git/Push.pm
 lib/Dist/Zilla/Plugin/Git/Tag.pm
 lib/Dist/Zilla/PluginBundle/Git.pm
+lib/Dist/Zilla/Role/Git/DirtyFiles.pm
 t/00-compile.t
 t/1-check.t
+t/2-commit-ws.t
 t/2-commit.t
 t/3-tag.t
+t/4-push-multi.t
 t/4-push.t
 t/author-critic.t
 t/check/Changes
 t/check/dist.ini
 t/check/foobar
+t/commit-ws/Changes
+t/commit-ws/dist.ini
 t/commit/Changes
 t/commit/dist.ini
+t/push-multi/Changes
+t/push-multi/dist.ini
 t/push/Changes
 t/push/dist.ini
 t/release-meta-yaml.t
@@ -2,11 +2,9 @@
 abstract: 'update your git repository after release'
 author:
   - 'Jerome Quelin'
-build_requires:
-  Module::Build: 0.35
-configure_requires:
-  Module::Build: 0.35
-generated_by: 'Dist::Zilla version 1.093371'
+build_requires: {}
+configure_requires: {}
+generated_by: 'Dist::Zilla version 1.100711'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -15,40 +13,43 @@ name: Dist-Zilla-Plugin-Git
 provides:
   Dist::Zilla::Plugin::Git:
     file: lib/Dist/Zilla/Plugin/Git.pm
-    version: 1.093410
+    version: 1.100760
   Dist::Zilla::Plugin::Git::Check:
     file: lib/Dist/Zilla/Plugin/Git/Check.pm
-    version: 1.093410
+    version: 1.100760
   Dist::Zilla::Plugin::Git::Commit:
     file: lib/Dist/Zilla/Plugin/Git/Commit.pm
-    version: 1.093410
+    version: 1.100760
   Dist::Zilla::Plugin::Git::Push:
     file: lib/Dist/Zilla/Plugin/Git/Push.pm
-    version: 1.093410
+    version: 1.100760
   Dist::Zilla::Plugin::Git::Tag:
     file: lib/Dist/Zilla/Plugin/Git/Tag.pm
-    version: 1.093410
+    version: 1.100760
   Dist::Zilla::PluginBundle::Git:
     file: lib/Dist/Zilla/PluginBundle/Git.pm
-    version: 1.093410
+    version: 1.100760
+  Dist::Zilla::Role::Git::DirtyFiles:
+    file: lib/Dist/Zilla/Role/Git/DirtyFiles.pm
+    version: 1.100760
 requires:
+  Class::MOP: 0
   Cwd: 0
-  Dist::Zilla: 1.093250
+  DateTime: 0
+  Dist::Zilla: 1.100660
   Dist::Zilla::Role::AfterRelease: 0
   Dist::Zilla::Role::BeforeRelease: 0
   Dist::Zilla::Role::PluginBundle: 0
   English: 0
-  ExtUtils::MakeMaker: 0
   File::Find: 0
-  File::Path: 2.07
-  File::Spec::Functions: 0
   File::Temp: 0
   Git::Wrapper: 0
-  Module::Build: 0
   Moose: 0
   Moose::Autobox: 0
+  Moose::Role: 0
   MooseX::Has::Sugar: 0
   MooseX::Types::Moose: 0
+  Path::Class: 0
   String::Formatter: 0
   Test::Exception: 0
   Test::More: 0
@@ -57,4 +58,4 @@ resources:
   MailingList: http://www.listbox.com/subscribe/?list_id=139292
   homepage: http://search.cpan.org/dist/Dist-Zilla-Plugin-Git/
   repository: http://github.com/jquelin/dist-zilla-plugin-git
-version: 1.093410
+version: 1.100760
@@ -1,39 +0,0 @@
-
-use strict;
-use warnings;
-
- BEGIN { require 5.008; } 
-
-use ExtUtils::MakeMaker;
-
-WriteMakefile(
-  DISTNAME  => 'Dist-Zilla-Plugin-Git',
-  NAME      => 'Dist::Zilla::Plugin::Git',
-  AUTHOR    => "Jerome\ Quelin",
-  ABSTRACT  => "update\ your\ git\ repository\ after\ release",
-  VERSION   => '1.093410',
-  EXE_FILES => [ qw() ],
-  (eval { ExtUtils::MakeMaker->VERSION(6.31) } ? (LICENSE => 'perl') : ()),
-  PREREQ_PM    => {
-    "MooseX::Has::Sugar" => '0',
-    "MooseX::Types::Moose" => '0',
-    "Dist::Zilla::Role::PluginBundle" => '0',
-    "Git::Wrapper" => '0',
-    "Dist::Zilla::Role::AfterRelease" => '0',
-    "File::Find" => '0',
-    "File::Path" => '2.07',
-    "File::Spec::Functions" => '0',
-    "Moose" => '0',
-    "English" => '0',
-    "Test::Exception" => '0',
-    "Moose::Autobox" => '0',
-    "Test::More" => '0',
-    "File::Temp" => '0',
-    "Dist::Zilla" => '1.093250',
-    "Dist::Zilla::Role::BeforeRelease" => '0',
-    "String::Formatter" => '0',
-    "Cwd" => '0',
-  },
-  test => {TESTS => 't/*.t'}
-);
-
@@ -1,7 +1,7 @@
 
 
 This archive contains the distribution Dist-Zilla-Plugin-Git, version
-1.093410:
+1.100760:
 
   update your git repository after release
 
@@ -5,47 +5,9 @@ copyright_holder = Jerome Quelin
 copyright_year   = 2009
 
 ; -- static meta-information
-[AutoVersion]
 [MetaResources]
 homepage    = http://search.cpan.org/dist/Dist-Zilla-Plugin-Git/
 repository  = http://github.com/jquelin/dist-zilla-plugin-git
 MailingList = http://www.listbox.com/subscribe/?list_id=139292
 
-; -- fetch & generate files
-[AllFiles]
-[CompileTests]
-[CriticTests]
-[MetaTests]
-[PodTests]
-
-; -- remove files
-[PruneCruft]
-[ManifestSkip]
-
-; -- get prereqs
-[AutoPrereq]
-
-; -- munge files
-[ExtraTests]
-[NextRelease]
-[PkgVersion]
-[PodWeaver]
-[Prepender]
-copyright = 1
-
-; -- dynamic meta-information
-[InstallDirs]
-[MetaProvides::Package]
-
-; -- generate meta files
-[License]
-[MakeMaker]
-[ModuleBuild]
-[MetaYAML]
-[Readme]
-[Manifest] ; should come last
-
-; -- release
-[CheckChangeLog]
-[@Git]
-[UploadToCPAN]
+[@JQUELIN]
@@ -11,21 +11,17 @@ use strict;
 use warnings;
 
 package Dist::Zilla::Plugin::Git::Check;
-our $VERSION = '1.093410';
+our $VERSION = '1.100760';
 # ABSTRACT: check your git repository before releasing
 
 use Git::Wrapper;
 use Moose;
-use MooseX::Has::Sugar;
-use MooseX::Types::Moose qw{ Str };
 
 with 'Dist::Zilla::Role::BeforeRelease';
+with 'Dist::Zilla::Role::Git::DirtyFiles';
 
 
-# -- attributes
-
-has filename => ( ro, isa=>Str, default => 'Changes' );
-
+# -- public methods
 
 sub before_release {
     my $self = shift;
@@ -41,33 +37,31 @@ sub before_release {
     @output = $git->diff( { cached=>1, 'name-status'=>1 } );
     if ( @output ) {
         my $errmsg =
-            "[Git] branch $branch has some changes staged for commit:\n" .
+            "branch $branch has some changes staged for commit:\n" .
             join "\n", map { "\t$_" } @output;
-        die "$errmsg\n";
+        $self->log_fatal($errmsg);
     }
 
-    # everything but changelog and dist.ini should be in a clean state
-    @output =
-        grep { $_ ne $self->filename }
-        grep { $_ ne 'dist.ini' }
-        $git->ls_files( { modified=>1, deleted=>1 } );
+    # everything but files listed in allow_dirty should be in a
+    # clean state
+    @output = $self->list_dirty_files($git);
     if ( @output ) {
         my $errmsg =
-            "[Git] branch $branch has some uncommitted files:\n" .
+            "branch $branch has some uncommitted files:\n" .
             join "\n", map { "\t$_" } @output;
-        die "$errmsg\n";
+        $self->log_fatal($errmsg);
     }
 
     # no files should be untracked
     @output = $git->ls_files( { others=>1, 'exclude-standard'=>1 } );
     if ( @output ) {
         my $errmsg =
-            "[Git] branch $branch has some untracked files:\n" .
+            "branch $branch has some untracked files:\n" .
             join "\n", map { "\t$_" } @output;
-        die "$errmsg\n";
+        $self->log_fatal($errmsg);
     }
 
-    $self->zilla->log( "[Git] branch $branch is in a clean state\n" );
+    $self->log( "branch $branch is in a clean state" );
 }
 
 
@@ -82,14 +76,16 @@ Dist::Zilla::Plugin::Git::Check - check your git repository before releasing
 
 =head1 VERSION
 
-version 1.093410
+version 1.100760
 
 =head1 SYNOPSIS
 
 In your F<dist.ini>:
 
     [Git::Check]
-    filename = Changes      ; this is the default
+    allow_dirty = dist.ini
+    allow_dirty = README
+    changelog = Changes      ; this is the default
 
 =head1 DESCRIPTION
 
@@ -102,8 +98,8 @@ following checks are performed before releasing:
 
 =item * there should be no untracked files in the working copy
 
-=item * the working copy should be clean. The changelog and F<dist.ini>
-can be modified locally, though.
+=item * the working copy should be clean. The files listed in
+C<allow_dirty> can be modified locally, though.
 
 =back
 
@@ -114,7 +110,12 @@ The plugin accepts the following options:
 
 =over 4
 
-=item * filename - the name of your changelog file. defaults to F<Changes>.
+=item * changelog - the name of your changelog file. defaults to F<Changes>.
+
+=item * allow_dirty - a file that is allowed to have local
+modifications.  This option may appear multiple times.  The default
+list is F<dist.ini> and the changelog file given by C<changelog>.  You
+can use C<allow_dirty => to prohibit all local modifications.
 
 =back
 
@@ -134,4 +135,5 @@ the same terms as the Perl 5 programming language system itself.
 =cut
 
 
-__END__
\ No newline at end of file
+__END__
+
@@ -11,8 +11,8 @@ use strict;
 use warnings;
 
 package Dist::Zilla::Plugin::Git::Commit;
-our $VERSION = '1.093410';
-# ABSTRACT: commit dist.ini and changelog
+our $VERSION = '1.100760';
+# ABSTRACT: commit dirty files
 
 use File::Temp           qw{ tempfile };
 use Git::Wrapper;
@@ -20,44 +20,79 @@ use Moose;
 use MooseX::Has::Sugar;
 use MooseX::Types::Moose qw{ Str };
 
+use String::Formatter method_stringf => {
+  -as => '_format_string',
+  codes => {
+    c => sub { $_[0]->_get_changes },
+    d => sub { require DateTime;
+               DateTime->now->format_cldr($_[1] || 'dd-MMM-yyyy') },
+    n => sub { "\n" },
+    N => sub { $_[0]->zilla->name },
+    v => sub { $_[0]->zilla->version },
+  },
+};
+
 with 'Dist::Zilla::Role::AfterRelease';
+with 'Dist::Zilla::Role::Git::DirtyFiles';
 
 
 # -- attributes
 
-has filename => ( ro, isa=>Str, default => 'Changes' );
+has commit_msg => ( ro, isa=>Str, default => 'v%v%n%n%c' );
+
+
+# -- public methods
 
 sub after_release {
     my $self = shift;
     my $git  = Git::Wrapper->new('.');
     my @output;
 
-    # check if changelog and dist.ini need to be committed
+    # check if there are dirty files that need to be committed.
     # at this time, we know that only those 2 files may remain modified,
     # otherwise before_release would have failed, ending the release
     # process.
-    @output =
-        grep { $_ eq 'dist.ini' || $_ eq $self->filename }
-        $git->ls_files( { modified=>1, deleted=>1 } );
+    @output = sort { lc $a cmp lc $b } $self->list_dirty_files($git, 1);
     return unless @output;
 
+    # write commit message in a temp file
+    my ($fh, $filename) = tempfile( 'DZP-git.XXXX', UNLINK => 1 );
+    print $fh $self->get_commit_message;
+    close $fh;
+
+    # commit the files in git
+    $git->add( @output );
+    $self->log_debug($_) for $git->commit( { file=>$filename } );
+    $self->log("Committed @output");
+}
+
+
+
+sub get_commit_message {
+    my $self = shift;
+
+    return _format_string($self->commit_msg, $self);
+} # end get_commit_message
+
+# -- private methods
+
+sub _get_changes {
+    my $self = shift;
+
     # parse changelog to find commit message
-    my $changelog = Dist::Zilla::File::OnDisk->new( { name => $self->filename } );
+    my $changelog = Dist::Zilla::File::OnDisk->new( { name => $self->changelog } );
     my $newver    = $self->zilla->version;
     my @content   =
-        grep { /^$newver\s+/ ... /^(\S|\s*$)/ }
+        grep { /^$newver\s+/ ... /^\S/ } # from newver to un-indented
         split /\n/, $changelog->content;
     shift @content; # drop the version line
+    # drop unindented last line and trailing blank lines
+    pop @content while ( @content && $content[-1] =~ /^(?:\S|\s*$)/ );
 
-    # write commit message in a temp file
-    my ($fh, $filename) = tempfile( 'DZP-git.XXXX', UNLINK => 1 );
-    print $fh join("\n", "v$newver\n", @content, ''); # add a final \n
-    close $fh;
+    # return commit message
+    return join("\n", @content, ''); # add a final \n
+} # end _get_changes
 
-    # commit the files in git
-    $git->add( 'dist.ini', $self->filename );
-    $git->commit( { file=>$filename } );
-}
 
 1;
 
@@ -66,33 +101,75 @@ sub after_release {
 
 =head1 NAME
 
-Dist::Zilla::Plugin::Git::Commit - commit dist.ini and changelog
+Dist::Zilla::Plugin::Git::Commit - commit dirty files
 
 =head1 VERSION
 
-version 1.093410
+version 1.100760
 
 =head1 SYNOPSIS
 
 In your F<dist.ini>:
 
     [Git::Commit]
-    filename = Changes      ; this is the default
+    changelog = Changes      ; this is the default
 
 =head1 DESCRIPTION
 
 Once the release is done, this plugin will record this fact in git by
 committing changelog and F<dist.ini>. The commit message will be taken
-from the changelog for this release.
+from the changelog for this release.  It will include lines between
+the current version and timestamp and the next non-indented line.
 
 The plugin accepts the following options:
 
 =over 4
 
-=item * filename - the name of your changelog file. defaults to F<Changes>.
+=item * changelog - the name of your changelog file. defaults to F<Changes>.
+
+=item * allow_dirty - a file that will be checked in if it is locally
+modified.  This option may appear multiple times.  The default
+list is F<dist.ini> and the changelog file given by C<changelog>.
+
+=item * commit_msg - the commit message to use. defaults to
+C<v%v%n%n%c>, meaning the version number and the list of changes.
+
+=back
+
+You can use the following codes in commit_msg:
+
+=over 4
+
+=item C<%c>
+
+The list of changes in the just-released version (read from C<changelog>).
+
+=item C<%{dd-MMM-yyyy}d>
+
+The current date.  You can use any CLDR format supported by
+L<DateTime>.  A bare C<%d> means C<%{dd-MMM-yyyy}d>.
+
+=item C<%n>
+
+a newline
+
+=item C<%N>
+
+the distribution name
+
+=item C<%v>
+
+the distribution version
 
 =back
 
+=head1 METHODS
+
+=head2 get_commit_message
+
+This method returns the commit message.  The default implementation
+reads the Changes file to get the list of changes in the just-released version.
+
 =for Pod::Coverage::TrustPod after_release
 
 =head1 AUTHOR
@@ -109,4 +186,5 @@ the same terms as the Perl 5 programming language system itself.
 =cut
 
 
-__END__
\ No newline at end of file
+__END__
+
@@ -11,28 +11,38 @@ use strict;
 use warnings;
 
 package Dist::Zilla::Plugin::Git::Push;
-our $VERSION = '1.093410';
+our $VERSION = '1.100760';
 # ABSTRACT: push current branch
 
 use Git::Wrapper;
 use Moose;
 use MooseX::Has::Sugar;
-use MooseX::Types::Moose qw{ Str };
+use MooseX::Types::Moose qw{ ArrayRef Str };
 
 with 'Dist::Zilla::Role::AfterRelease';
 
+sub mvp_multivalue_args { qw(push_to) }
 
 # -- attributes
 
-has filename => ( ro, isa=>Str, default => 'Changes' );
+has push_to => (
+  is   => 'ro',
+  isa  => 'ArrayRef[Str]',
+  lazy => 1,
+  default => sub { [ qw(origin) ] },
+);
+
 
 sub after_release {
     my $self = shift;
     my $git  = Git::Wrapper->new('.');
 
     # push everything on remote branch
-    $git->push;
-    $git->push( { tags=>1 } );
+    for my $remote ( @{ $self->push_to } ) { 
+      $self->log("pushing to $remote");
+      $self->log_debug($_) for $git->push( $remote );
+      $self->log_debug($_) for $git->push( { tags=>1 },  $remote );
+    }
 }
 
 1;
@@ -46,14 +56,14 @@ Dist::Zilla::Plugin::Git::Push - push current branch
 
 =head1 VERSION
 
-version 1.093410
+version 1.100760
 
 =head1 SYNOPSIS
 
 In your F<dist.ini>:
 
     [Git::Push]
-    filename = Changes      ; this is the default
+    push_to = origin      ; this is the default
 
 =head1 DESCRIPTION
 
@@ -64,11 +74,15 @@ The plugin accepts the following options:
 
 =over 4
 
-=item * filename - the name of your changelog file. defaults to F<Changes>.
+=item * 
+
+push_to - the name of the a remote to push to. The default is F<origin>.
+This may be specified multiple times to push to multiple repositories.
 
 =back
 
 =for Pod::Coverage::TrustPod after_release
+    mvp_multivalue_args
 
 =head1 AUTHOR
 
@@ -84,4 +98,5 @@ the same terms as the Perl 5 programming language system itself.
 =cut
 
 
-__END__
\ No newline at end of file
+__END__
+
@@ -11,7 +11,7 @@ use strict;
 use warnings;
 
 package Dist::Zilla::Plugin::Git::Tag;
-our $VERSION = '1.093410';
+our $VERSION = '1.100760';
 # ABSTRACT: tag the new version
 
 use Git::Wrapper;
@@ -21,28 +21,49 @@ use MooseX::Types::Moose qw{ Str };
 use String::Formatter method_stringf => {
   -as => '_format_tag',
   codes => {
+    d => sub { require DateTime;
+               DateTime->now->format_cldr($_[1] || 'dd-MMM-yyyy') },
+    n => sub { "\n" },
+    N => sub { $_[0]->name },
     v => sub { $_[0]->version },
   },
 };
 
+with 'Dist::Zilla::Role::BeforeRelease';
 with 'Dist::Zilla::Role::AfterRelease';
 
 
 # -- attributes
 
-has filename   => ( ro, isa=>Str, default => 'Changes' );
-has tag_format => ( ro, isa=>Str, default => 'v%v' );
+has tag_format  => ( ro, isa=>Str, default => 'v%v' );
+has tag_message => ( ro, isa=>Str, default => 'v%v' );
 
 
 # -- role implementation
 
+sub before_release {
+    my $self = shift;
+    my $git  = Git::Wrapper->new('.');
+
+    # Make sure a tag with the new version doesn't exist yet:
+    my $tag = _format_tag($self->tag_format, $self->zilla);
+    $self->log_fatal("tag $tag already exists")
+        if $git->tag('-l', $tag );
+}
+
 sub after_release {
     my $self = shift;
     my $git  = Git::Wrapper->new('.');
 
+    # Make an annotated tag if tag_message, lightweight tag otherwise:
+    my @opts = $self->tag_message
+        ? ( '-m' => _format_tag($self->tag_message, $self->zilla) )
+        : ();
+
     # create a tag with the new version
     my $tag = _format_tag($self->tag_format, $self->zilla);
-    $git->tag( $tag );
+    $git->tag( @opts, $tag );
+    $self->log("Tagged $tag");
 }
 
 1;
@@ -56,32 +77,64 @@ Dist::Zilla::Plugin::Git::Tag - tag the new version
 
 =head1 VERSION
 
-version 1.093410
+version 1.100760
 
 =head1 SYNOPSIS
 
 In your F<dist.ini>:
 
     [Git::Tag]
-    filename = Changes      ; this is the default
+    tag_format  = v%v       ; this is the default
+    tag_message = v%v       ; this is the default
 
 =head1 DESCRIPTION
 
 Once the release is done, this plugin will record this fact in git by
-creating a tag.
+creating a tag.  By default, it makes an annotated tag.  You can set
+the C<tag_message> attribute to change the message.  If you set
+C<tag_message> to the empty string, it makes a lightweight tag.
+
+It also checks before the release to ensure the tag to be created
+doesn't already exist.  (You would have to manually delete the
+existing tag before you could release the same version again, but that
+is almost never a good idea.)
 
 The plugin accepts the following options:
 
 =over 4
 
-=item * filename - the name of your changelog file. Defaults to F<Changes>.
+=item * tag_format - format of the tag to apply. Defaults to C<v%v>.
+
+=item * tag_message - format of the commit message. Defaults to C<v%v>.
+Use C<tag_message = > to create a lightweight tag.
+
+=back
+
+You can use the following codes in both options:
+
+=over 4
+
+=item C<%{dd-MMM-yyyy}d>
+
+The current date.  You can use any CLDR format supported by
+L<DateTime>.  A bare C<%d> means C<%{dd-MMM-yyyy}d>.
+
+=item C<%n>
 
-=item * tag_format - format of the tag to apply. C<%v> will be
-replaced by the dist version. Defaults to C<v%v>.
+a newline
+
+=item C<%N>
+
+the distribution name
+
+=item C<%v>
+
+the distribution version
 
 =back
 
 =for Pod::Coverage::TrustPod after_release
+    before_release
 
 =head1 AUTHOR
 
@@ -97,4 +150,5 @@ the same terms as the Perl 5 programming language system itself.
 =cut
 
 
-__END__
\ No newline at end of file
+__END__
+
@@ -11,9 +11,10 @@ use strict;
 use warnings;
 
 package Dist::Zilla::Plugin::Git;
-our $VERSION = '1.093410';
+our $VERSION = '1.100760';
 # ABSTRACT: update your git repository after release
 
+use Dist::Zilla 1.100660;
 1;
 
 
@@ -25,7 +26,7 @@ Dist::Zilla::Plugin::Git - update your git repository after release
 
 =head1 VERSION
 
-version 1.093410
+version 1.100760
 
 =head1 DESCRIPTION
 
@@ -94,4 +95,6 @@ the same terms as the Perl 5 programming language system itself.
 =cut
 
 
-__END__
\ No newline at end of file
+__END__
+
+
@@ -11,11 +11,11 @@ use strict;
 use warnings;
 
 package Dist::Zilla::PluginBundle::Git;
-our $VERSION = '1.093410';
+our $VERSION = '1.100760';
 # ABSTRACT: all git plugins in one go
 
 use Moose;
-use Moose::Autobox;
+use Class::MOP;
 
 with 'Dist::Zilla::Role::PluginBundle';
 
@@ -25,14 +25,17 @@ sub bundle_config {
     my $arg   = $section->{payload};
 
     # bundle all git plugins
-    my @classes =
-        map { "Dist::Zilla::Plugin::Git::$_" }
-        qw{ Check Commit Tag Push };
+    my @names   = qw{ Check Commit Tag Push };
 
-    # make sure all plugins exist
-    eval "require $_; 1" or die for @classes; ## no critic ProhibitStringyEval
+    my @config;
 
-    return @classes->map(sub { [ "$class/$_" => $_ => $arg ] })->flatten;
+    for my $name (@names) {
+        my $class = "Dist::Zilla::Plugin::Git::$name";
+        Class::MOP::load_class($class);
+        push @config, [ "$section->{name}/$name" => $class => $arg ];
+    }
+
+    return @config;
 }
 
 
@@ -49,14 +52,20 @@ Dist::Zilla::PluginBundle::Git - all git plugins in one go
 
 =head1 VERSION
 
-version 1.093410
+version 1.100760
 
 =head1 SYNOPSIS
 
 In your F<dist.ini>:
 
     [@Git]
-    filename = Changes        ; this is the default
+    changelog   = Changes             ; this is the default
+    allow_dirty = dist.ini            ; see Git::Check...
+    allow_dirty = Changes             ; ... and Git::Commit
+    commit_msg  = v%v%n%n%c           ; see Git::Commit
+    tag_format  = %v                  ; see Git::Tag
+    tag_message = %v                  ; see Git::Tag
+    push_to     = origin              ; see Git::Push
 
 =head1 DESCRIPTION
 
@@ -85,4 +94,5 @@ the same terms as the Perl 5 programming language system itself.
 =cut
 
 
-__END__
\ No newline at end of file
+__END__
+
@@ -0,0 +1,116 @@
+# 
+# This file is part of Dist-Zilla-Plugin-Git
+# 
+# This software is copyright (c) 2009 by Jerome Quelin.
+# 
+# This is free software; you can redistribute it and/or modify it under
+# the same terms as the Perl 5 programming language system itself.
+# 
+use 5.008;
+use strict;
+use warnings;
+
+package Dist::Zilla::Role::Git::DirtyFiles;
+our $VERSION = '1.100760';
+# ABSTRACT: provide the allow_dirty & changelog attributes
+
+use Moose::Role;
+use Moose::Autobox;
+use MooseX::Has::Sugar;
+use MooseX::Types::Moose qw{ ArrayRef Str };
+
+
+# -- attributes
+
+
+has allow_dirty => (
+  ro, lazy,
+  isa     => ArrayRef[Str],
+  builder => '_build_allow_dirty',
+);
+has changelog => ( ro, isa=>Str, default => 'Changes' );
+
+sub mvp_multivalue_args { qw(allow_dirty) }
+
+
+# -- builders & initializers
+
+sub _build_allow_dirty { [ 'dist.ini', shift->changelog ] }
+
+
+
+
+sub list_dirty_files
+{
+  my ($self, $git, $listAllowed) = @_;
+
+  my %allowed = map { $_ => 1 } $self->allow_dirty->flatten;
+
+  return grep { $allowed{$_} ? $listAllowed : !$listAllowed }
+      $git->ls_files( { modified=>1, deleted=>1 } );
+} # end list_dirty_files
+
+
+no Moose::Role;
+no MooseX::Has::Sugar;
+1;
+
+
+=pod
+
+=head1 NAME
+
+Dist::Zilla::Role::Git::DirtyFiles - provide the allow_dirty & changelog attributes
+
+=head1 VERSION
+
+version 1.100760
+
+=head1 DESCRIPTION
+
+This role is used within the git plugin to work with files that are
+dirty in the local git checkout.
+
+=head1 ATTRIBUTES
+
+=head2 allow_dirty
+
+A list of files that are allowed to be dirty in the git checkout.
+Defaults to C<dist.ini> and the changelog (as defined per the
+C<changelog> attribute.
+
+=head2 changelog
+
+The name of the changelog. Defaults to C<Changes>.
+
+=head1 METHODS
+
+=head2 list_dirty_files
+
+  my @dirty = $plugin->list_dirty_files($git, $listAllowed);
+
+This returns a list of the modified or deleted files in C<$git>,
+filtered against the C<allow_dirty> attribute.  If C<$listAllowed> is
+true, only allowed files are listed.  If it's false, only files that
+are not allowed to be dirty are listed.
+
+In scalar context, returns the number of dirty files.
+
+=for Pod::Coverage::TrustPod mvp_multivalue_args
+
+=head1 AUTHOR
+
+  Jerome Quelin
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2009 by Jerome Quelin.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
+
+
+__END__
+
@@ -13,6 +13,7 @@ use warnings;
 
 use Test::More;
 use File::Find;
+use File::Temp qw{ tempdir };
 
 my @modules;
 find(
@@ -31,16 +32,21 @@ find(
 my @scripts = glob "bin/*";
 
 plan tests => scalar(@modules) + scalar(@scripts);
-    
-is( qx{ $^X -Ilib -M$_ -e "print '$_ ok'" }, "$_ ok", "$_ loaded ok" )
-    for sort @modules;
-    
-SKIP: {
-    eval "use Test::Script; 1;";
-    skip "Test::Script needed to test script compilation", scalar(@scripts) if $@;
-    foreach my $file ( @scripts ) {
-        my $script = $file;
-        $script =~ s!.*/!!;
-        script_compiles_ok( $file, "$script script compiles" );
+
+{
+    # fake home for cpan-testers
+    # no fake requested ## local $ENV{HOME} = tempdir( CLEANUP => 1 );
+
+    is( qx{ $^X -Ilib -M$_ -e "print '$_ ok'" }, "$_ ok", "$_ loaded ok" )
+        for sort @modules;
+
+    SKIP: {
+        eval "use Test::Script; 1;";
+        skip "Test::Script needed to test script compilation", scalar(@scripts) if $@;
+        foreach my $file ( @scripts ) {
+            my $script = $file;
+            $script =~ s!.*/!!;
+            script_compiles_ok( $file, "$script script compiles" );
+        }
     }
-}
\ No newline at end of file
+}
@@ -11,16 +11,15 @@
 use strict;
 use warnings;
 
-use Dist::Zilla           1.093250;
-use File::Path            2.07 qw{ remove_tree };
-use File::Spec::Functions qw{ catdir };
+use Dist::Zilla     1.093250;
 use Git::Wrapper;
-use Test::More            tests => 4;
+use Path::Class;
+use Test::More      tests => 4;
 use Test::Exception;
 
 
 # build fake repository
-chdir( catdir('t', 'check') );
+chdir( dir('t', 'check') );
 system "git init";
 my $git   = Git::Wrapper->new('.');
 my $zilla = Dist::Zilla->from_config;
@@ -50,7 +49,7 @@ append_to_file('dist.ini', "\n");
 lives_ok { $zilla->release } 'Changes and dist.ini can be modified';
 
 # clean & exit
-remove_tree( '.git' );
+dir( '.git' )->rmtree;
 unlink 'Foo-1.23.tar.gz', '.gitignore';
 exit;
 
@@ -59,4 +58,4 @@ sub append_to_file {
     open my $fh, '>>', $file or die "can't open $file: $!";
     print $fh @lines;
     close $fh;
-}
\ No newline at end of file
+}
@@ -0,0 +1,58 @@
+#!perl
+# 
+# This file is part of Dist-Zilla-Plugin-Git
+# 
+# This software is copyright (c) 2009 by Jerome Quelin.
+# 
+# This is free software; you can redistribute it and/or modify it under
+# the same terms as the Perl 5 programming language system itself.
+# 
+
+use strict;
+use warnings;
+
+use Dist::Zilla  1.093250;
+use Git::Wrapper;
+use Path::Class;
+use Test::More   tests => 1;
+
+# build fake repository
+chdir( dir('t', 'commit-ws') );
+system "git init";
+my $git = Git::Wrapper->new('.');
+$git->config( 'user.name'  => 'dzp-git test' );
+$git->config( 'user.email' => 'dzp-git@test' );
+$git->add( qw{ dist.ini Changes } );
+$git->commit( { message => 'initial commit' } );
+
+# do a release, with changes and dist.ini updated
+append_to_file('Changes',  "\n");
+append_to_file('dist.ini', "\n");
+my $zilla = Dist::Zilla->from_config;
+$zilla->release;
+
+# check if dist.ini and changelog have been committed
+my ($log) = $git->log( 'HEAD' );
+my $expected = << "HERE";
+v1.23
+
+- foo
+
+- bar
+
+- baz
+HERE
+
+is( $log->message, $expected, 'commit message taken from changelog' );
+
+# clean & exit
+dir( '.git' )->rmtree;
+unlink 'Foo-1.23.tar.gz';
+exit;
+
+sub append_to_file {
+    my ($file, @lines) = @_;
+    open my $fh, '>>', $file or die "can't open $file: $!";
+    print $fh @lines;
+    close $fh;
+}
@@ -11,16 +11,17 @@
 use strict;
 use warnings;
 
-use Dist::Zilla           1.093250;
-use File::Path            2.07 qw{ remove_tree };
-use File::Spec::Functions qw{ catdir };
+use Dist::Zilla  1.093250;
 use Git::Wrapper;
-use Test::More            tests => 1;
+use Path::Class;
+use Test::More   tests => 1;
 
 # build fake repository
-chdir( catdir('t', 'commit') );
+chdir( dir('t', 'commit') );
 system "git init";
 my $git = Git::Wrapper->new('.');
+$git->config( 'user.name'  => 'dzp-git test' );
+$git->config( 'user.email' => 'dzp-git@test' );
 $git->add( qw{ dist.ini Changes } );
 $git->commit( { message => 'initial commit' } );
 
@@ -35,7 +36,7 @@ my ($log) = $git->log( 'HEAD' );
 is( $log->message, "v1.23\n\n- foo\n- bar\n- baz\n", 'commit message taken from changelog' );
 
 # clean & exit
-remove_tree( '.git' );
+dir( '.git' )->rmtree;
 unlink 'Foo-1.23.tar.gz';
 exit;
 
@@ -44,4 +45,4 @@ sub append_to_file {
     open my $fh, '>>', $file or die "can't open $file: $!";
     print $fh @lines;
     close $fh;
-}
\ No newline at end of file
+}
@@ -11,16 +11,17 @@
 use strict;
 use warnings;
 
-use Dist::Zilla           1.093250;
-use File::Path            2.07 qw{ remove_tree };
-use File::Spec::Functions qw{ catdir };
+use Dist::Zilla  1.093250;
 use Git::Wrapper;
-use Test::More            tests => 2;
+use Path::Class;
+use Test::More   tests => 3;
 
 # build fake repository
-chdir( catdir('t', 'tag') );
+chdir( dir('t', 'tag') );
 system "git init";
 my $git = Git::Wrapper->new('.');
+$git->config( 'user.name'  => 'dzp-git test' );
+$git->config( 'user.email' => 'dzp-git@test' );
 $git->add( qw{ dist.ini Changes } );
 $git->commit( { message => 'initial commit' } );
 
@@ -33,7 +34,13 @@ my @tags = $git->tag;
 is( scalar(@tags), 1, 'one tag created' );
 is( $tags[0], 'v1.23', 'new tag created after new version' );
 
+# attempting to release again should fail
+$zilla = Dist::Zilla->from_config;
+eval { $zilla->release };
+
+like($@, qr/tag v1\.23 already exists/, 'prohibit duplicate tag');
+
 # clean & exit
-remove_tree( '.git' );
+dir('.git')->rmtree;
 unlink 'Foo-1.23.tar.gz';
-exit;
\ No newline at end of file
+exit;
@@ -0,0 +1,70 @@
+#!perl
+# 
+# This file is part of Dist-Zilla-Plugin-Git
+# 
+# This software is copyright (c) 2009 by Jerome Quelin.
+# 
+# This is free software; you can redistribute it and/or modify it under
+# the same terms as the Perl 5 programming language system itself.
+# 
+
+use strict;
+use warnings;
+
+use Dist::Zilla  1.093250;
+use Cwd          qw{ getcwd  };
+use File::Temp   qw{ tempdir };
+use Git::Wrapper;
+use Path::Class;
+use Test::More   tests => 6;
+
+# build fake repository
+chdir( dir('t', 'push-multi') );
+dir( '.git' )->rmtree if -d '.git'; # clean up from any prior run
+system "git init";
+my $git = Git::Wrapper->new('.');
+$git->config( 'user.name'  => 'dzp-git test' );
+$git->config( 'user.email' => 'dzp-git@test' );
+$git->add( qw{ dist.ini Changes } );
+$git->commit( { message => 'initial commit' } );
+
+# create a clone, and use it to set up origin
+my $clone1 = tempdir( CLEANUP => 1 );
+my $clone2 = tempdir( CLEANUP => 1 );
+my $curr  = getcwd;
+$git->clone( { quiet=>1, 'no-checkout'=>1, bare=>1 }, $curr, $clone1 );
+$git->clone( { quiet=>1, 'no-checkout'=>1, bare=>1 }, $curr, $clone2 );
+$git->remote('add', 'origin', $clone1);
+$git->remote('add', 'another', $clone2);
+$git->config('branch.master.remote', 'origin');
+$git->config('branch.master.merge', 'refs/heads/master');
+
+# do the release
+append_to_file('Changes',  "\n");
+append_to_file('dist.ini', "\n");
+my $zilla = Dist::Zilla->from_config;
+$zilla->release;
+
+for my $c ( $clone1, $clone2 ) {
+  # check if everything was pushed
+  $git = Git::Wrapper->new( $c );
+  my ($log) = $git->log( 'HEAD' );
+  is( $log->message, "v1.23\n\n- foo\n- bar\n- baz\n", "commit pushed to $c" );
+
+  # check if tag has been correctly created
+  my @tags = $git->tag;
+  is( scalar(@tags), 1, 'one tag pushed' );
+  is( $tags[0], 'v1.23', 'new tag created after new version' );
+}
+
+# clean & exit
+dir( '.git' )->rmtree;
+unlink 'Foo-1.23.tar.gz';
+exit;
+
+sub append_to_file {
+    my ($file, @lines) = @_;
+    open my $fh, '>>', $file or die "can't open $file: $!";
+    print $fh @lines;
+    close $fh;
+}
@@ -11,30 +11,30 @@
 use strict;
 use warnings;
 
-use Dist::Zilla           1.093250;
-use File::Path            2.07 qw{ remove_tree };
-use Cwd                   qw{ getcwd  };
-use File::Temp            qw{ tempdir };
-use File::Spec::Functions qw{ catdir  };
+use Dist::Zilla  1.093250;
+use Cwd          qw{ getcwd  };
+use File::Temp   qw{ tempdir };
 use Git::Wrapper;
-use Test::More            tests => 3;
+use Path::Class;
+use Test::More   tests => 3;
 
 # build fake repository
-chdir( catdir('t', 'push') );
+chdir( dir('t', 'push') );
+dir( '.git' )->rmtree if -d '.git'; # clean up from any prior run
 system "git init";
 my $git = Git::Wrapper->new('.');
+$git->config( 'user.name'  => 'dzp-git test' );
+$git->config( 'user.email' => 'dzp-git@test' );
 $git->add( qw{ dist.ini Changes } );
 $git->commit( { message => 'initial commit' } );
 
 # create a clone, and use it to set up origin
 my $clone = tempdir( CLEANUP => 1 );
 my $curr  = getcwd;
-{
-    chdir $clone;
-    system qq{ git clone $curr };
-}
-chdir $curr;
-$git->remote('add', 'origin', catdir($clone, 'push'));
+$git->clone( { quiet=>1, 'no-checkout'=>1, bare=>1 }, $curr, $clone );
+$git->remote('add', 'origin', $clone);
+$git->config('branch.master.remote', 'origin');
+$git->config('branch.master.merge', 'refs/heads/master');
 
 # do the release
 append_to_file('Changes',  "\n");
@@ -43,7 +43,7 @@ my $zilla = Dist::Zilla->from_config;
 $zilla->release;
 
 # check if everything was pushed
-$git = Git::Wrapper->new( catdir($clone, 'push') );
+$git = Git::Wrapper->new( $clone );
 my ($log) = $git->log( 'HEAD' );
 is( $log->message, "v1.23\n\n- foo\n- bar\n- baz\n", 'commit pushed' );
 
@@ -53,7 +53,7 @@ is( scalar(@tags), 1, 'one tag pushed' );
 is( $tags[0], 'v1.23', 'new tag created after new version' );
 
 # clean & exit
-remove_tree( '.git' );
+dir( '.git' )->rmtree;
 unlink 'Foo-1.23.tar.gz';
 exit;
 
@@ -62,4 +62,4 @@ sub append_to_file {
     open my $fh, '>>', $file or die "can't open $file: $!";
     print $fh @lines;
     close $fh;
-}
\ No newline at end of file
+}
@@ -16,6 +16,9 @@ BEGIN {
 }
 
 
+use strict;
+use warnings;
+
 use Test::More;
 use English qw(-no_match_vars);
 
@@ -2,6 +2,7 @@ name    = Foo
 version = 1.23
 author  = foobar
 license = Perl_5
+abstract = Test Library
 copyright_holder = foobar
 copyright_year   = 2009
 
@@ -2,6 +2,7 @@ name    = Foo
 version = 1.23
 author  = foobar
 license = Perl_5
+abstract = Test Library
 copyright_holder = foobar
 copyright_year   = 2009
 
@@ -0,0 +1,21 @@
+Changes
+
+1.23 2009-11-16 19:15:45 CET
+
+ - foo
+
+ - bar
+
+ - baz
+
+1.22 2009-11-15 12:13:14 CET
+
+ - biff
+
+ - boff
+
+
+
+
+
+
@@ -0,0 +1,17 @@
+name    = Foo
+version = 1.23
+author  = foobar
+license = Perl_5
+abstract = Test Library
+copyright_holder = foobar
+copyright_year   = 2009
+
+[FakeRelease]
+[Git::Commit]
+
+
+
+
+
+
+
@@ -2,6 +2,7 @@ name    = Foo
 version = 1.23
 author  = foobar
 license = Perl_5
+abstract = Test Library
 copyright_holder = foobar
 copyright_year   = 2009
 
@@ -0,0 +1,9 @@
+Changes
+
+1.23 2009-11-16 19:15:45 CET
+ - foo
+ - bar
+ - baz
+
+
+
@@ -0,0 +1,16 @@
+name    = Foo
+version = 1.23
+author  = foobar
+license = Perl_5
+abstract = Test Library
+copyright_holder = foobar
+copyright_year   = 2009
+
+[FakeRelease]
+[Git::Commit]
+[Git::Tag]
+[Git::Push]
+push_to = origin
+push_to = another
+
+
@@ -2,6 +2,7 @@ name    = Foo
 version = 1.23
 author  = foobar
 license = Perl_5
+abstract = Test Library
 copyright_holder = foobar
 copyright_year   = 2009