├── AUTHOR_PLEDGE ├── CODE_OF_CONDUCT.md ├── CONTRIBUTORS ├── Changes ├── INSTALL ├── LICENSE ├── MANIFEST ├── META.json ├── META.yml ├── Makefile.PL ├── README.mkdn ├── SIGNATURE ├── bin └── git-cpan ├── cpanfile ├── doap.xml ├── lib └── Git │ └── CPAN │ ├── Patch.pm │ └── Patch │ ├── Command │ ├── Clone.pm │ ├── FormatPatch.pm │ ├── Import.pm │ ├── SendEmail.pm │ ├── SendPatch.pm │ ├── Sources.pm │ ├── Squash.pm │ ├── Update.pm │ └── Which.pm │ ├── Import.pm │ ├── Release.pm │ └── Role │ ├── Git.pm │ └── Patch.pm ├── t ├── 00-compile.t ├── 00-load.t ├── 00-report-prereqs.dd ├── 00-report-prereqs.t ├── clone.t └── corpus │ └── Git-CPAN-Patch-0.4.5.tar.gz ├── xauth ├── clone-from-github.t └── clone-from-module.t └── xt └── release └── unused-vars.t /AUTHOR_PLEDGE: -------------------------------------------------------------------------------- 1 | 2 | # CPAN Covenant for Git-CPAN-Patch 3 | 4 | I, Yanick Champoux , hereby give modules@perl.org permission to grant co-maintainership 5 | to Git-CPAN-Patch, if all the following conditions are met: 6 | 7 | (1) I haven't released the module for a year or more 8 | (2) There are outstanding issues in the module's public bug tracker 9 | (3) Email to my CPAN email address hasn't been answered after a month 10 | (4) The requester wants to make worthwhile changes that will benefit CPAN 11 | 12 | In the event of my death, then the time-limits in (1) and (3) do not apply. 13 | 14 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at yanick@cpan.org. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | 2 | # GIT-CPAN-PATCH CONTRIBUTORS # 3 | 4 | This is the (likely incomplete) list of people who have helped 5 | make this distribution what it is, either via code contributions, 6 | patches, bug reports, help with troubleshooting, etc. A huge 7 | 'thank you' to all of them. 8 | 9 | * 2shortplanks 10 | * Arthur Axel 'fREW' Schmidt 11 | * brian d foy 12 | * chocolateboy 13 | * Dagfinn Ilmari Mannsåker 14 | * Graham Knop 15 | * Lisa Hare 16 | * Michael G. Schwern 17 | * Mike Doherty 18 | * Mike Doherty 19 | * Pedro Melo 20 | * Peter Valdemar Mørch 21 | * Reini Urban 22 | * sdeseille 23 | * Slaven Rezic 24 | * Stefan Hornburg (Racke) 25 | * temp0 26 | * Tim Bunce via RT 27 | * Yanick Champoux 28 | * Yuval Kogman 29 | * Zakariyya Mughal 30 | 31 | 32 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for Git::CPAN::Patch 2 | 3 | 2.5.0 2022-03-06 4 | [ENHANCEMENTS] 5 | - Remove dependency on CLASS module 6 | 7 | [STATISTICS] 8 | - code churn: 3 files changed, 239 insertions(+), 238 deletions(-) 9 | 10 | 2.4.0 2021-09-19 11 | [ENHANCEMENTS] 12 | - Only prefix tag with 'v' if needed. (GH#42, zmughal) 13 | - Add a --nocheck negation version of --check. (GH#41, zmughal) 14 | 15 | [STATISTICS] 16 | - code churn: 6 files changed, 118 insertions(+), 16 deletions(-) 17 | 18 | 2.3.4 2018-08-24 19 | [BUG FIXES] 20 | - fix signatures in ::Command::Clone. (GH#38) 21 | 22 | [STATISTICS] 23 | - code churn: 2 files changed, 16 insertions(+), 7 deletions(-) 24 | 25 | 2.3.3 2018-08-21 26 | [DOCUMENTATION] 27 | - Fix sendpatch typo in POD. (GH#36, Racke) 28 | 29 | [MISC] 30 | - Use native signatures instead of Method::Signatures::Simple, which also 31 | mean minimal perl version is now 5.20.0. 32 | 33 | [STATISTICS] 34 | - code churn: 16 files changed, 105 insertions(+), 75 deletions(-) 35 | 36 | 2.3.2 2017-12-22 37 | [BUG FIXES] 38 | - source command was erroneously using 'vcs' attribute. (GH#35, ilmari) 39 | 40 | [STATISTICS] 41 | - code churn: 5 files changed, 97 insertions(+), 8 deletions(-) 42 | 43 | 2.3.1 2017-01-12 44 | [BUG FIXES] 45 | - Remove dependency on MooseX::Role::Tempdir. (GH#33, Sebastien Deseille) 46 | 47 | [STATISTICS] 48 | - code churn: 3 files changed, 32 insertions(+), 14 deletions(-) 49 | 50 | 2.3.0 2016-04-13 51 | - perlcritic tweaks, add documentation, better die messages. (GH#32, 52 | temp0) 53 | 54 | [ENHANCEMENTS] 55 | - 'git cpan import' now has options '--author_name' and '--author_email' 56 | to force author to those values. (GH#31) 57 | 58 | [STATISTICS] 59 | - code churn: 8 files changed, 78 insertions(+), 45 deletions(-) 60 | 61 | 2.2.1 2016-02-06 62 | [BUG FIXES] 63 | - Test was failing if color.ui was set to always. (GH#29, reported by 64 | grinnz) 65 | 66 | [STATISTICS] 67 | - code churn: 3 files changed, 24 insertions(+), 13 deletions(-) 68 | 69 | 2.2.0 2015-08-09 70 | [BUG FIXES] 71 | - Allow git to prompt user when calling sendemail (GH#25, Arthur Axel fREW 72 | Schmidt) 73 | - Tags were printed with the warning "at line blah". (GH#22) 74 | 75 | [ENHANCEMENTS] 76 | - Improve error message. (GH#24, frioux) 77 | 78 | [NEW FEATURES] 79 | - Store module name in config instead of relying on commit messages 80 | (frioux, GH#26) 81 | 82 | [STATISTICS] 83 | - code churn: 8 files changed, 219 insertions(+), 438 deletions(-) 84 | 85 | 2.1.0 2015-06-01 86 | [ENHANCEMENTS] 87 | - Be a little more clever about finding out if the META repo is git-based. 88 | 89 | [STATISTICS] 90 | - code churn: 3 files changed, 22 insertions(+), 4 deletions(-) 91 | 92 | 2.0.4 2015-04-19 93 | [BUG FIXES] 94 | - Tests were failing because of space-sensitivity. (lharey, GH#21) 95 | 96 | [ENHANCEMENTS] 97 | - Move to MetaCPAN::Client. (GH#19) 98 | 99 | [STATISTICS] 100 | - code churn: 14 files changed, 233 insertions(+), 210 deletions(-) 101 | 102 | 2.0.3 2014-03-17 103 | [BUG FIXES] 104 | - Deal with any archives and other fixes. (RT#92928, reported by Alexandr 105 | Ciornii) 106 | 107 | [STATISTICS] 108 | - code churn: 7 files changed, 79 insertions(+), 26 deletions(-) 109 | 110 | 2.0.2 2014-03-03 111 | [BUG FIXES] 112 | - Author and date of release take precedence over the GIT_* env variables. 113 | (RT#93481, reported by Slaven Rezic) 114 | 115 | [DOCUMENTATION] 116 | - Remove mention of option '--backpan' for import. (RT#93482, raised by 117 | Slaven Rezic) 118 | 119 | [STATISTICS] 120 | - code churn: 4 files changed, 18 insertions(+), 42 deletions(-) 121 | 122 | 2.0.1 2014-02-15 123 | [BUG FIXES] 124 | - Added dependency to Git::Repository::Plugin::AUTOLOAD. 125 | - Re-introduced Pod::Weaver (spotted by Neil Bowers). 126 | 127 | [STATISTICS] 128 | - code churn: 3 files changed, 14 insertions(+), 4 deletions(-) 129 | 130 | 2.0.0 2014-02-12 131 | [API CHANGES] 132 | - Will now clone of the official git repository, if there is one. 133 | 134 | [STATISTICS] 135 | - code churn: 13 files changed, 385 insertions(+), 64 deletions(-) 136 | 137 | 1.3.1 2013-07-27 138 | [BUG FIXES] 139 | - Bump minimal Perl requirements to 5.10.1 (for smartmatches). 140 | 141 | [STATISTICS] 142 | - code churn: 2 files changed, 10 insertions(+), 2 deletions(-) 143 | 144 | 1.3.0 2013-07-18 145 | [ENHANCEMENTS] 146 | - Silence smart-match warnings for 5.18+ 147 | 148 | [STATISTICS] 149 | - code churn: 2 files changed, 25 insertions(+), 16 deletions(-) 150 | 151 | 1.2.1 2013-07-15 152 | [BUG FIXES] 153 | - Was using 'return $foo or die' instead of 'return $foo || die'. 154 | 155 | [STATISTICS] 156 | - code churn: 2 files changed, 11 insertions(+), 4 deletions(-) 157 | 158 | 1.2.0 2013-04-21 159 | [ENHANCEMENTS] 160 | - Move to Method:::Signature::Simple as M::S doesn't work with 5.17.11. 161 | (GH#14, ilmari) 162 | 163 | [STATISTICS] 164 | - code churn: 14 files changed, 32 insertions(+), 16 deletions(-) 165 | 166 | 1.1.2 2013-04-14 167 | [BUG FIXES] 168 | - bump dependency for MooseX::App to solve boolean argument problem. 169 | 170 | [STATISTICS] 171 | - code churn: 2 files changed, 9 insertions(+), 10 deletions(-) 172 | 173 | 1.1.1 2013-04-01 174 | [BUG FIXES] 175 | - changes in latest MooseX::App broke Git::CPAN::Patch (RT#84349, 176 | reported by Peter Valdemar Morch) 177 | 178 | [STATISTICS] 179 | - code churn: 8 files changed, 47 insertions(+), 18 deletions(-) 180 | 181 | 1.1.0 2013-01-19 182 | [ENHANCEMENTS] 183 | - Simplify code after MooseX::App improvements (maros rocks) 184 | 185 | [STATISTICS] 186 | - code churn: 2 files changed, 19 insertions(+), 75 deletions(-) 187 | 188 | 1.0.3 2013-01-08 189 | [BUG FIXES] 190 | - Specify Method::Signature minimal version. 191 | 192 | [STATISTICS] 193 | - code churn: 2 files changed, 14 insertions(+), 7 deletions(-) 194 | 195 | 1.0.2 2013-01-03 196 | [BUG FIXES] 197 | - Removed s///r use. 198 | 199 | [STATISTICS] 200 | - code churn: 2 files changed, 17 insertions(+), 7 deletions(-) 201 | 202 | 1.0.1 2013-01-01 203 | [BUG FIXES] 204 | - Hide the MooseX::App monkeypatching from the cpan indexer. 205 | 206 | [DOCUMENTATION] 207 | - Change 'git cpan' for the new 'git-cpan'. 208 | 209 | [STATISTICS] 210 | - code churn: 9 files changed, 41 insertions(+), 25 deletions(-) 211 | 212 | 1.0.0 2013-01-01 213 | [API CHANGES] 214 | - Major rewrite using MooseX::App 215 | 216 | [ENHANCEMENTS] 217 | - cpan-git-import now uses metacpan instead of CPANPLUS 218 | - removed gitpan support, as it has gone dormant 219 | 220 | [STATISTICS] 221 | - code churn: 38 files changed, 1594 insertions(+), 1244 deletions(-) 222 | 223 | 0.8.0 2012-05-22 224 | - code churn: 1 files changed, 4 insertions(+), 86 deletions(-) 225 | 226 | [ENHANCEMENTS] 227 | - Added new command 'cpan-clone', which operates like git-clone [Mike 228 | Doherty] 229 | 230 | 0.7.0 2011-11-12 231 | [ENHANCEMENTS] 232 | - 'git cpan-init' now accepts a '--vcs' argument 233 | - new command 'git cpan-sources' 234 | 235 | 0.6.1 2011-06-05 236 | [BUG FIXES] 237 | - pass '--no-chain-reply-to' explicitly to 'git-send-email'. 238 | - git-cpan-sendpatch and git-cpan-sendemail now accept '--compose'. 239 | (thanks to Olaf Alders for the bug report) 240 | 241 | 0.6.0 2011-03-06 242 | - don't blindly import perl if the module is core, but rather suggest to 243 | use the Perl git repository instead. Thanks to Rafael Kitover for the 244 | bug report (RT#66416) 245 | 246 | 0.5.0 2011-03-05 247 | - use Git::Repository instead of Git for the git interactions. Thanks to 248 | brian d foy and Philippe Bruhat for the patches. 249 | 250 | 0.4.6 2010-10-11 251 | - move 'File::chmod' before 'autodie' to hush the warnings. (RT#61034) 252 | 253 | 0.4.5 2010-08-16 254 | - fix --force documentation/error message/support for git-cpan-import. 255 | Thanks to chocolateboy. 256 | 257 | 0.4.4 2010-06-07 258 | - Small doc fix for git-backpan-init. Thanks to chocolateboy. 259 | - Fix "Can't use string as an ARRAY ref" error introduced in 0.3.2. Thanks 260 | to chocolateboy. 261 | - Fix repo initialization as per the documentation. Thanks to 262 | chocolateboy. 263 | 264 | 0.4.3 2010-06-06 265 | - Still have troubles with the version number and the indexer. 266 | 267 | 0.4.2 2010-06-06 268 | - Return to the format vx.y.z to keep the CPAN indexer happy. Bleh. 269 | 270 | 0.4.1 2010-06-06 271 | - Fix the META.yml so that the version is correct. 272 | 273 | 0.4.0 2010-06-05 274 | - Fix git-cpan-which so that it doesn't return a leading space. Thanks to 275 | Tim Bunce. (rt-58001) 276 | - Check at install time if Git.pm (and thus Git) is present. 277 | - Add a --gitpan option for git-cpan0-import 278 | 279 | 0.3.2 2010-04-25 280 | - Explicitly requires perl 5.10. (rt-54368, reported by Jesse Vincent) 281 | - Preventive dying if we don't see the body_* functions. (rt-46715, 282 | reported by Alexandr Ciornii) 283 | - Moved Module::Build to 'configure_requires'. (rt-44925, reported by 284 | Jesse Vincent) 285 | - create_makefile_pl now set to small 286 | 287 | 0.3.1 2009-12-20 288 | - Getting git cpan-import --backpan to work again 289 | - Adding dependencies for Parse::BACKPAN::Packages, File::Temp, CLASS and 290 | File::chmod 291 | - Adding a 'use 5.010' 292 | 293 | 0.3.0 2009-12-20 294 | - Temporary directory are removed after used. Thanks to Slaven Rezic. 295 | - git-backpan-init, --mkdir make full directory paths. Thanks to Schwern. 296 | - git-backpan-init, add a --backpan option to supply your own backpan 297 | URL. Thanks to Schwern. 298 | - Guts of git-cpan-import moved to Git::CPAN::Patch::Import. Thanks to 299 | Schwern. 300 | - git-cpan-* just install themselves as regular scripts instead of hunting 301 | the git directory, as git will pull commands from anyway in the PATH. 302 | Thanks to Schwern. 303 | - Distributions no longer lower cased. Thanks to Schwern. 304 | - Date bug fixed. Thanks to Schwern. 305 | - Adding File::Path to the dependencies. 306 | - Include the CPAN id of the author in the commit log. Thanks to Schwern. 307 | - PPM files are now skipped. Thanks to Schwern. 308 | - Skip perl distributions. Thanks to Schwern. 309 | - Have Archive::Extract prefer binary programs for performance. Thanks to 310 | Schwern. 311 | - Overwrite existing version tags if there's two releases with the same 312 | versions. Thanks to Schwern. 313 | - Some archives have broken permissions. Fix them after extraction. 314 | Thanks to Schwern. 315 | - Record the file we imported from in the commit message. Thanks to 316 | Schwern. 317 | - Use File::chmod instead of shell chmod to avoid shell quoting problems. 318 | Thanks to Schwern. 319 | - Don't try to tag releases with no versions. Thanks to 320 | Schwern. 321 | - Tag .1 as 0.1. git doesn't like a tag named .1 Thanks to Schwern. 322 | - Skip empty tarballs. Thanks to Schwern. 323 | - Skip bad archives. Thanks to Schwern. 324 | 325 | 0.2.1 Thur Sept 3 2009 326 | - git-cpan-import is working with new version of Git. Thanks 327 | to Alexandr Ciornii. (rt#48713) 328 | - Require CPANPLUS 0.84 or higher. Thanks to Alexandr Ciornii. (rt#48713) 329 | 330 | 0.2.0 2009-07-11 331 | - New --parent option for git-cpan-import 332 | 333 | 0.1.7 2009-05-31 334 | - git-backpan-init doesn't choke on bad versions but skip them (rt bug 335 | 46469) 336 | 337 | 0.1.6 2009-05-12 338 | - git-backpan-init doesn't choke on non-monotone version numbers anymore 339 | (rt bug 45994) 340 | - git-cpan-import gets a new --checkversion option 341 | - Adding Module::Build as an explicit dependency and passthrough 342 | Makefile.PL 343 | 344 | 0.1.5 2009-03-28 345 | - Fixed typo in git-cpan-squash doc (rt bug 43294), patch by Slaven Rezic 346 | - Removed warning from git-cpan-import, patch by Pedro Melo 347 | - scripts' shebang line now set to Perl's interpreter used by 348 | Build.PL (rt bug 43366) 349 | 350 | 0.1.4 2009-02-14 351 | - backpan-init now calls cpan-import properly (fix by Slaven Rezic) 352 | - CPANPlUS added as dependency 353 | - Documentation correction (patch by 2shortplanks) 354 | 355 | 0.1.3 2009-02-05 356 | - Of course, removing 5.10 requirements in Build.PL would help... *sigh* 357 | 358 | 0.1.2 2009-02-03 359 | - Made scripts Perl 5.8-compatible 360 | 361 | 0.1.1 2009-02-03 362 | - Removed dependency on List::MoreUtils from Build.PL 363 | 364 | 0.1.0 2009-02-02 365 | - First CPAN release. 366 | - Massive restructuration and explosion of features, thanks to Yuval 367 | Kogman. 368 | 369 | 0.0.1 December 2008 370 | - Original scripts are published alongside the article "CPAN Patching with 371 | Git" in issue 5.1 of the Perl Review. 372 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | This is the Perl distribution Git-CPAN-Patch. 2 | 3 | Installing Git-CPAN-Patch is straightforward. 4 | 5 | ## Installation with cpanm 6 | 7 | If you have cpanm, you only need one line: 8 | 9 | % cpanm Git::CPAN::Patch 10 | 11 | If it does not have permission to install modules to the current perl, cpanm 12 | will automatically set up and install to a local::lib in your home directory. 13 | See the local::lib documentation (https://metacpan.org/pod/local::lib) for 14 | details on enabling it in your environment. 15 | 16 | ## Installing with the CPAN shell 17 | 18 | Alternatively, if your CPAN shell is set up, you should just be able to do: 19 | 20 | % cpan Git::CPAN::Patch 21 | 22 | ## Manual installation 23 | 24 | As a last resort, you can manually install it. Download the tarball, untar it, 25 | install configure prerequisites (see below), then build it: 26 | 27 | % perl Makefile.PL 28 | % make && make test 29 | 30 | Then install it: 31 | 32 | % make install 33 | 34 | On Windows platforms, you should use `dmake` or `nmake`, instead of `make`. 35 | 36 | If your perl is system-managed, you can create a local::lib in your home 37 | directory to install modules to. For details, see the local::lib documentation: 38 | https://metacpan.org/pod/local::lib 39 | 40 | The prerequisites of this distribution will also have to be installed manually. The 41 | prerequisites are listed in one of the files: `MYMETA.yml` or `MYMETA.json` generated 42 | by running the manual build process described above. 43 | 44 | ## Configure Prerequisites 45 | 46 | This distribution requires other modules to be installed before this 47 | distribution's installer can be run. They can be found under the 48 | "configure_requires" key of META.yml or the 49 | "{prereqs}{configure}{requires}" key of META.json. 50 | 51 | ## Other Prerequisites 52 | 53 | This distribution may require additional modules to be installed after running 54 | Makefile.PL. 55 | Look for prerequisites in the following phases: 56 | 57 | * to run make, PHASE = build 58 | * to use the module code itself, PHASE = runtime 59 | * to run tests, PHASE = test 60 | 61 | They can all be found in the "PHASE_requires" key of MYMETA.yml or the 62 | "{prereqs}{PHASE}{requires}" key of MYMETA.json. 63 | 64 | ## Documentation 65 | 66 | Git-CPAN-Patch documentation is available as POD. 67 | You can run `perldoc` from a shell to read the documentation: 68 | 69 | % perldoc Git::CPAN::Patch 70 | 71 | For more information on installing Perl modules via CPAN, please see: 72 | https://www.cpan.org/modules/INSTALL.html 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 2 | 3 | This is free software; you can redistribute it and/or modify it under 4 | the same terms as the Perl 5 programming language system itself. 5 | 6 | Terms of the Perl programming language system itself 7 | 8 | a) the GNU General Public License as published by the Free 9 | Software Foundation; either version 1, or (at your option) any 10 | later version, or 11 | b) the "Artistic License" 12 | 13 | --- The GNU General Public License, Version 1, February 1989 --- 14 | 15 | This software is Copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 16 | 17 | This is free software, licensed under: 18 | 19 | The GNU General Public License, Version 1, February 1989 20 | 21 | GNU GENERAL PUBLIC LICENSE 22 | Version 1, February 1989 23 | 24 | Copyright (C) 1989 Free Software Foundation, Inc. 25 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 26 | 27 | Everyone is permitted to copy and distribute verbatim copies 28 | of this license document, but changing it is not allowed. 29 | 30 | Preamble 31 | 32 | The license agreements of most software companies try to keep users 33 | at the mercy of those companies. By contrast, our General Public 34 | License is intended to guarantee your freedom to share and change free 35 | software--to make sure the software is free for all its users. The 36 | General Public License applies to the Free Software Foundation's 37 | software and to any other program whose authors commit to using it. 38 | You can use it for your programs, too. 39 | 40 | When we speak of free software, we are referring to freedom, not 41 | price. Specifically, the General Public License is designed to make 42 | sure that you have the freedom to give away or sell copies of free 43 | software, that you receive source code or can get it if you want it, 44 | that you can change the software or use pieces of it in new free 45 | programs; and that you know you can do these things. 46 | 47 | To protect your rights, we need to make restrictions that forbid 48 | anyone to deny you these rights or to ask you to surrender the rights. 49 | These restrictions translate to certain responsibilities for you if you 50 | distribute copies of the software, or if you modify it. 51 | 52 | For example, if you distribute copies of a such a program, whether 53 | gratis or for a fee, you must give the recipients all the rights that 54 | you have. You must make sure that they, too, receive or can get the 55 | source code. And you must tell them their rights. 56 | 57 | We protect your rights with two steps: (1) copyright the software, and 58 | (2) offer you this license which gives you legal permission to copy, 59 | distribute and/or modify the software. 60 | 61 | Also, for each author's protection and ours, we want to make certain 62 | that everyone understands that there is no warranty for this free 63 | software. If the software is modified by someone else and passed on, we 64 | want its recipients to know that what they have is not the original, so 65 | that any problems introduced by others will not reflect on the original 66 | authors' reputations. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | GNU GENERAL PUBLIC LICENSE 72 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 73 | 74 | 0. This License Agreement applies to any program or other work which 75 | contains a notice placed by the copyright holder saying it may be 76 | distributed under the terms of this General Public License. The 77 | "Program", below, refers to any such program or work, and a "work based 78 | on the Program" means either the Program or any work containing the 79 | Program or a portion of it, either verbatim or with modifications. Each 80 | licensee is addressed as "you". 81 | 82 | 1. You may copy and distribute verbatim copies of the Program's source 83 | code as you receive it, in any medium, provided that you conspicuously and 84 | appropriately publish on each copy an appropriate copyright notice and 85 | disclaimer of warranty; keep intact all the notices that refer to this 86 | General Public License and to the absence of any warranty; and give any 87 | other recipients of the Program a copy of this General Public License 88 | along with the Program. You may charge a fee for the physical act of 89 | transferring a copy. 90 | 91 | 2. You may modify your copy or copies of the Program or any portion of 92 | it, and copy and distribute such modifications under the terms of Paragraph 93 | 1 above, provided that you also do the following: 94 | 95 | a) cause the modified files to carry prominent notices stating that 96 | you changed the files and the date of any change; and 97 | 98 | b) cause the whole of any work that you distribute or publish, that 99 | in whole or in part contains the Program or any part thereof, either 100 | with or without modifications, to be licensed at no charge to all 101 | third parties under the terms of this General Public License (except 102 | that you may choose to grant warranty protection to some or all 103 | third parties, at your option). 104 | 105 | c) If the modified program normally reads commands interactively when 106 | run, you must cause it, when started running for such interactive use 107 | in the simplest and most usual way, to print or display an 108 | announcement including an appropriate copyright notice and a notice 109 | that there is no warranty (or else, saying that you provide a 110 | warranty) and that users may redistribute the program under these 111 | conditions, and telling the user how to view a copy of this General 112 | Public License. 113 | 114 | d) You may charge a fee for the physical act of transferring a 115 | copy, and you may at your option offer warranty protection in 116 | exchange for a fee. 117 | 118 | Mere aggregation of another independent work with the Program (or its 119 | derivative) on a volume of a storage or distribution medium does not bring 120 | the other work under the scope of these terms. 121 | 122 | 3. You may copy and distribute the Program (or a portion or derivative of 123 | it, under Paragraph 2) in object code or executable form under the terms of 124 | Paragraphs 1 and 2 above provided that you also do one of the following: 125 | 126 | a) accompany it with the complete corresponding machine-readable 127 | source code, which must be distributed under the terms of 128 | Paragraphs 1 and 2 above; or, 129 | 130 | b) accompany it with a written offer, valid for at least three 131 | years, to give any third party free (except for a nominal charge 132 | for the cost of distribution) a complete machine-readable copy of the 133 | corresponding source code, to be distributed under the terms of 134 | Paragraphs 1 and 2 above; or, 135 | 136 | c) accompany it with the information you received as to where the 137 | corresponding source code may be obtained. (This alternative is 138 | allowed only for noncommercial distribution and only if you 139 | received the program in object code or executable form alone.) 140 | 141 | Source code for a work means the preferred form of the work for making 142 | modifications to it. For an executable file, complete source code means 143 | all the source code for all modules it contains; but, as a special 144 | exception, it need not include source code for modules which are standard 145 | libraries that accompany the operating system on which the executable 146 | file runs, or for standard header files or definitions files that 147 | accompany that operating system. 148 | 149 | 4. You may not copy, modify, sublicense, distribute or transfer the 150 | Program except as expressly provided under this General Public License. 151 | Any attempt otherwise to copy, modify, sublicense, distribute or transfer 152 | the Program is void, and will automatically terminate your rights to use 153 | the Program under this License. However, parties who have received 154 | copies, or rights to use copies, from you under this General Public 155 | License will not have their licenses terminated so long as such parties 156 | remain in full compliance. 157 | 158 | 5. By copying, distributing or modifying the Program (or any work based 159 | on the Program) you indicate your acceptance of this license to do so, 160 | and all its terms and conditions. 161 | 162 | 6. Each time you redistribute the Program (or any work based on the 163 | Program), the recipient automatically receives a license from the original 164 | licensor to copy, distribute or modify the Program subject to these 165 | terms and conditions. You may not impose any further restrictions on the 166 | recipients' exercise of the rights granted herein. 167 | 168 | 7. The Free Software Foundation may publish revised and/or new versions 169 | of the General Public License from time to time. Such new versions will 170 | be similar in spirit to the present version, but may differ in detail to 171 | address new problems or concerns. 172 | 173 | Each version is given a distinguishing version number. If the Program 174 | specifies a version number of the license which applies to it and "any 175 | later version", you have the option of following the terms and conditions 176 | either of that version or of any later version published by the Free 177 | Software Foundation. If the Program does not specify a version number of 178 | the license, you may choose any version ever published by the Free Software 179 | Foundation. 180 | 181 | 8. If you wish to incorporate parts of the Program into other free 182 | programs whose distribution conditions are different, write to the author 183 | to ask for permission. For software which is copyrighted by the Free 184 | Software Foundation, write to the Free Software Foundation; we sometimes 185 | make exceptions for this. Our decision will be guided by the two goals 186 | of preserving the free status of all derivatives of our free software and 187 | of promoting the sharing and reuse of software generally. 188 | 189 | NO WARRANTY 190 | 191 | 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 192 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 193 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 194 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 195 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 196 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 197 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 198 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 199 | REPAIR OR CORRECTION. 200 | 201 | 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 202 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 203 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 204 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 205 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 206 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 207 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 208 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 209 | POSSIBILITY OF SUCH DAMAGES. 210 | 211 | END OF TERMS AND CONDITIONS 212 | 213 | Appendix: How to Apply These Terms to Your New Programs 214 | 215 | If you develop a new program, and you want it to be of the greatest 216 | possible use to humanity, the best way to achieve this is to make it 217 | free software which everyone can redistribute and change under these 218 | terms. 219 | 220 | To do so, attach the following notices to the program. It is safest to 221 | attach them to the start of each source file to most effectively convey 222 | the exclusion of warranty; and each file should have at least the 223 | "copyright" line and a pointer to where the full notice is found. 224 | 225 | 226 | Copyright (C) 19yy 227 | 228 | This program is free software; you can redistribute it and/or modify 229 | it under the terms of the GNU General Public License as published by 230 | the Free Software Foundation; either version 1, or (at your option) 231 | any later version. 232 | 233 | This program is distributed in the hope that it will be useful, 234 | but WITHOUT ANY WARRANTY; without even the implied warranty of 235 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 236 | GNU General Public License for more details. 237 | 238 | You should have received a copy of the GNU General Public License 239 | along with this program; if not, write to the Free Software 240 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 241 | 242 | 243 | Also add information on how to contact you by electronic and paper mail. 244 | 245 | If the program is interactive, make it output a short notice like this 246 | when it starts in an interactive mode: 247 | 248 | Gnomovision version 69, Copyright (C) 19xx name of author 249 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 250 | This is free software, and you are welcome to redistribute it 251 | under certain conditions; type `show c' for details. 252 | 253 | The hypothetical commands `show w' and `show c' should show the 254 | appropriate parts of the General Public License. Of course, the 255 | commands you use may be called something other than `show w' and `show 256 | c'; they could even be mouse-clicks or menu items--whatever suits your 257 | program. 258 | 259 | You should also get your employer (if you work as a programmer) or your 260 | school, if any, to sign a "copyright disclaimer" for the program, if 261 | necessary. Here a sample; alter the names: 262 | 263 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 264 | program `Gnomovision' (a program to direct compilers to make passes 265 | at assemblers) written by James Hacker. 266 | 267 | , 1 April 1989 268 | Ty Coon, President of Vice 269 | 270 | That's all there is to it! 271 | 272 | 273 | --- The Artistic License 1.0 --- 274 | 275 | This software is Copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 276 | 277 | This is free software, licensed under: 278 | 279 | The Artistic License 1.0 280 | 281 | The Artistic License 282 | 283 | Preamble 284 | 285 | The intent of this document is to state the conditions under which a Package 286 | may be copied, such that the Copyright Holder maintains some semblance of 287 | artistic control over the development of the package, while giving the users of 288 | the package the right to use and distribute the Package in a more-or-less 289 | customary fashion, plus the right to make reasonable modifications. 290 | 291 | Definitions: 292 | 293 | - "Package" refers to the collection of files distributed by the Copyright 294 | Holder, and derivatives of that collection of files created through 295 | textual modification. 296 | - "Standard Version" refers to such a Package if it has not been modified, 297 | or has been modified in accordance with the wishes of the Copyright 298 | Holder. 299 | - "Copyright Holder" is whoever is named in the copyright or copyrights for 300 | the package. 301 | - "You" is you, if you're thinking about copying or distributing this Package. 302 | - "Reasonable copying fee" is whatever you can justify on the basis of media 303 | cost, duplication charges, time of people involved, and so on. (You will 304 | not be required to justify it to the Copyright Holder, but only to the 305 | computing community at large as a market that must bear the fee.) 306 | - "Freely Available" means that no fee is charged for the item itself, though 307 | there may be fees involved in handling the item. It also means that 308 | recipients of the item may redistribute it under the same conditions they 309 | received it. 310 | 311 | 1. You may make and give away verbatim copies of the source form of the 312 | Standard Version of this Package without restriction, provided that you 313 | duplicate all of the original copyright notices and associated disclaimers. 314 | 315 | 2. You may apply bug fixes, portability fixes and other modifications derived 316 | from the Public Domain or from the Copyright Holder. A Package modified in such 317 | a way shall still be considered the Standard Version. 318 | 319 | 3. You may otherwise modify your copy of this Package in any way, provided that 320 | you insert a prominent notice in each changed file stating how and when you 321 | changed that file, and provided that you do at least ONE of the following: 322 | 323 | a) place your modifications in the Public Domain or otherwise make them 324 | Freely Available, such as by posting said modifications to Usenet or an 325 | equivalent medium, or placing the modifications on a major archive site 326 | such as ftp.uu.net, or by allowing the Copyright Holder to include your 327 | modifications in the Standard Version of the Package. 328 | 329 | b) use the modified Package only within your corporation or organization. 330 | 331 | c) rename any non-standard executables so the names do not conflict with 332 | standard executables, which must also be provided, and provide a separate 333 | manual page for each non-standard executable that clearly documents how it 334 | differs from the Standard Version. 335 | 336 | d) make other distribution arrangements with the Copyright Holder. 337 | 338 | 4. You may distribute the programs of this Package in object code or executable 339 | form, provided that you do at least ONE of the following: 340 | 341 | a) distribute a Standard Version of the executables and library files, 342 | together with instructions (in the manual page or equivalent) on where to 343 | get the Standard Version. 344 | 345 | b) accompany the distribution with the machine-readable source of the Package 346 | with your modifications. 347 | 348 | c) accompany any non-standard executables with their corresponding Standard 349 | Version executables, giving the non-standard executables non-standard 350 | names, and clearly documenting the differences in manual pages (or 351 | equivalent), together with instructions on where to get the Standard 352 | Version. 353 | 354 | d) make other distribution arrangements with the Copyright Holder. 355 | 356 | 5. You may charge a reasonable copying fee for any distribution of this 357 | Package. You may charge any fee you choose for support of this Package. You 358 | may not charge a fee for this Package itself. However, you may distribute this 359 | Package in aggregate with other (possibly commercial) programs as part of a 360 | larger (possibly commercial) software distribution provided that you do not 361 | advertise this Package as a product of your own. 362 | 363 | 6. The scripts and library files supplied as input to or produced as output 364 | from the programs of this Package do not automatically fall under the copyright 365 | of this Package, but belong to whomever generated them, and may be sold 366 | commercially, and may be aggregated with this Package. 367 | 368 | 7. C or perl subroutines supplied by you and linked into this Package shall not 369 | be considered part of this Package. 370 | 371 | 8. The name of the Copyright Holder may not be used to endorse or promote 372 | products derived from this software without specific prior written permission. 373 | 374 | 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 375 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 376 | MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 377 | 378 | The End 379 | 380 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | AUTHOR_PLEDGE 2 | CODE_OF_CONDUCT.md 3 | CONTRIBUTORS 4 | Changes 5 | INSTALL 6 | LICENSE 7 | MANIFEST 8 | META.json 9 | META.yml 10 | Makefile.PL 11 | README.mkdn 12 | SIGNATURE 13 | bin/git-cpan 14 | cpanfile 15 | doap.xml 16 | lib/Git/CPAN/Patch.pm 17 | lib/Git/CPAN/Patch/Command/Clone.pm 18 | lib/Git/CPAN/Patch/Command/FormatPatch.pm 19 | lib/Git/CPAN/Patch/Command/Import.pm 20 | lib/Git/CPAN/Patch/Command/SendEmail.pm 21 | lib/Git/CPAN/Patch/Command/SendPatch.pm 22 | lib/Git/CPAN/Patch/Command/Sources.pm 23 | lib/Git/CPAN/Patch/Command/Squash.pm 24 | lib/Git/CPAN/Patch/Command/Update.pm 25 | lib/Git/CPAN/Patch/Command/Which.pm 26 | lib/Git/CPAN/Patch/Import.pm 27 | lib/Git/CPAN/Patch/Release.pm 28 | lib/Git/CPAN/Patch/Role/Git.pm 29 | lib/Git/CPAN/Patch/Role/Patch.pm 30 | t/00-compile.t 31 | t/00-load.t 32 | t/00-report-prereqs.dd 33 | t/00-report-prereqs.t 34 | t/clone.t 35 | t/corpus/Git-CPAN-Patch-0.4.5.tar.gz 36 | xauth/clone-from-github.t 37 | xauth/clone-from-module.t 38 | xt/release/unused-vars.t 39 | -------------------------------------------------------------------------------- /META.json: -------------------------------------------------------------------------------- 1 | { 2 | "abstract" : "Patch CPAN modules using Git", 3 | "author" : [ 4 | "Yanick Champoux " 5 | ], 6 | "dynamic_config" : 0, 7 | "generated_by" : "Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010", 8 | "license" : [ 9 | "perl_5" 10 | ], 11 | "meta-spec" : { 12 | "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", 13 | "version" : 2 14 | }, 15 | "name" : "Git-CPAN-Patch", 16 | "prereqs" : { 17 | "configure" : { 18 | "requires" : { 19 | "ExtUtils::MakeMaker" : "0" 20 | }, 21 | "suggests" : { 22 | "JSON::PP" : "2.27300" 23 | } 24 | }, 25 | "develop" : { 26 | "requires" : { 27 | "Test::More" : "0.96", 28 | "Test::Vars" : "0" 29 | } 30 | }, 31 | "runtime" : { 32 | "requires" : { 33 | "Archive::Any" : "0", 34 | "Archive::Extract" : "0", 35 | "BackPAN::Index" : "0", 36 | "CPAN::Meta" : "0", 37 | "CPAN::ParseDistribution" : "0", 38 | "CPANPLUS" : "0", 39 | "Cwd" : "0", 40 | "DateTime" : "0", 41 | "File::Basename" : "0", 42 | "File::Copy" : "0", 43 | "File::Find" : "0", 44 | "File::Path" : "0", 45 | "File::Spec::Functions" : "0", 46 | "File::Temp" : "0", 47 | "File::chdir" : "0", 48 | "File::chmod" : "0", 49 | "Git::Repository" : "0", 50 | "Git::Repository::Plugin::AUTOLOAD" : "0", 51 | "LWP::Simple" : "0", 52 | "LWP::UserAgent" : "0", 53 | "List::Pairwise" : "0", 54 | "MetaCPAN::API" : "0", 55 | "MetaCPAN::Client" : "0", 56 | "Moose" : "0", 57 | "Moose::Role" : "0", 58 | "MooseX::App" : "1.21", 59 | "MooseX::App::Command" : "0", 60 | "MooseX::App::Role" : "0", 61 | "MooseX::SemiAffordanceAccessor" : "0", 62 | "Path::Class" : "0", 63 | "Path::Tiny" : "0", 64 | "Pod::Usage" : "0", 65 | "autodie" : "0", 66 | "experimental" : "0", 67 | "perl" : "v5.20.0", 68 | "strict" : "0", 69 | "version" : "0", 70 | "warnings" : "0" 71 | } 72 | }, 73 | "test" : { 74 | "recommends" : { 75 | "CPAN::Meta" : "2.120900" 76 | }, 77 | "requires" : { 78 | "Carp" : "0", 79 | "DDP" : "0", 80 | "ExtUtils::MakeMaker" : "0", 81 | "File::Spec" : "0", 82 | "IO::Handle" : "0", 83 | "IPC::Open3" : "0", 84 | "Test::MockObject" : "0", 85 | "Test::More" : "0" 86 | } 87 | } 88 | }, 89 | "provides" : { 90 | "Git::CPAN::Patch" : { 91 | "file" : "lib/Git/CPAN/Patch.pm", 92 | "version" : "v2.5.0" 93 | }, 94 | "Git::CPAN::Patch::Command::Clone" : { 95 | "file" : "lib/Git/CPAN/Patch/Command/Clone.pm", 96 | "version" : "v2.5.0" 97 | }, 98 | "Git::CPAN::Patch::Command::FormatPatch" : { 99 | "file" : "lib/Git/CPAN/Patch/Command/FormatPatch.pm", 100 | "version" : "v2.5.0" 101 | }, 102 | "Git::CPAN::Patch::Command::Import" : { 103 | "file" : "lib/Git/CPAN/Patch/Command/Import.pm", 104 | "version" : "v2.5.0" 105 | }, 106 | "Git::CPAN::Patch::Command::SendEmail" : { 107 | "file" : "lib/Git/CPAN/Patch/Command/SendEmail.pm", 108 | "version" : "v2.5.0" 109 | }, 110 | "Git::CPAN::Patch::Command::SendPatch" : { 111 | "file" : "lib/Git/CPAN/Patch/Command/SendPatch.pm", 112 | "version" : "v2.5.0" 113 | }, 114 | "Git::CPAN::Patch::Command::Sources" : { 115 | "file" : "lib/Git/CPAN/Patch/Command/Sources.pm", 116 | "version" : "v2.5.0" 117 | }, 118 | "Git::CPAN::Patch::Command::Squash" : { 119 | "file" : "lib/Git/CPAN/Patch/Command/Squash.pm", 120 | "version" : "v2.5.0" 121 | }, 122 | "Git::CPAN::Patch::Command::Update" : { 123 | "file" : "lib/Git/CPAN/Patch/Command/Update.pm", 124 | "version" : "v2.5.0" 125 | }, 126 | "Git::CPAN::Patch::Command::Which" : { 127 | "file" : "lib/Git/CPAN/Patch/Command/Which.pm", 128 | "version" : "v2.5.0" 129 | }, 130 | "Git::CPAN::Patch::Import" : { 131 | "file" : "lib/Git/CPAN/Patch/Import.pm", 132 | "version" : "v2.5.0" 133 | }, 134 | "Git::CPAN::Patch::Release" : { 135 | "file" : "lib/Git/CPAN/Patch/Release.pm", 136 | "version" : "v2.5.0" 137 | }, 138 | "Git::CPAN::Patch::Role::Git" : { 139 | "file" : "lib/Git/CPAN/Patch/Role/Git.pm", 140 | "version" : "v2.5.0" 141 | }, 142 | "Git::CPAN::Patch::Role::Patch" : { 143 | "file" : "lib/Git/CPAN/Patch/Role/Patch.pm", 144 | "version" : "v2.5.0" 145 | } 146 | }, 147 | "release_status" : "stable", 148 | "resources" : { 149 | "bugtracker" : { 150 | "web" : "https://github.com/yanick/git-cpan-patch/issues" 151 | }, 152 | "homepage" : "https://github.com/yanick/git-cpan-patch", 153 | "repository" : { 154 | "type" : "git", 155 | "url" : "https://github.com/yanick/git-cpan-patch.git", 156 | "web" : "https://github.com/yanick/git-cpan-patch" 157 | } 158 | }, 159 | "version" : "2.5.0", 160 | "x_author_pledge" : { 161 | "version" : 1 162 | }, 163 | "x_authority" : "cpan:YANICK", 164 | "x_contributor_covenant" : { 165 | "version" : 0.02 166 | }, 167 | "x_contributors" : [ 168 | "2shortplanks ", 169 | "Arthur Axel 'fREW' Schmidt ", 170 | "brian d foy ", 171 | "chocolateboy ", 172 | "Dagfinn Ilmari Manns\u00e5ker ", 173 | "Graham Knop ", 174 | "Lisa Hare ", 175 | "Michael G. Schwern ", 176 | "Mike Doherty ", 177 | "Mike Doherty ", 178 | "Pedro Melo ", 179 | "Peter Valdemar M\u00f8rch ", 180 | "Reini Urban ", 181 | "sdeseille ", 182 | "Slaven Rezic ", 183 | "Stefan Hornburg (Racke) ", 184 | "temp0 ", 185 | "Tim Bunce via RT ", 186 | "Yanick Champoux ", 187 | "Yuval Kogman ", 188 | "Zakariyya Mughal " 189 | ], 190 | "x_generated_by_perl" : "v5.30.0", 191 | "x_serialization_backend" : "Cpanel::JSON::XS version 4.12", 192 | "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" 193 | } 194 | 195 | -------------------------------------------------------------------------------- /META.yml: -------------------------------------------------------------------------------- 1 | --- 2 | abstract: 'Patch CPAN modules using Git' 3 | author: 4 | - 'Yanick Champoux ' 5 | build_requires: 6 | Carp: '0' 7 | DDP: '0' 8 | ExtUtils::MakeMaker: '0' 9 | File::Spec: '0' 10 | IO::Handle: '0' 11 | IPC::Open3: '0' 12 | Test::MockObject: '0' 13 | Test::More: '0' 14 | configure_requires: 15 | ExtUtils::MakeMaker: '0' 16 | dynamic_config: 0 17 | generated_by: 'Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010' 18 | license: perl 19 | meta-spec: 20 | url: http://module-build.sourceforge.net/META-spec-v1.4.html 21 | version: '1.4' 22 | name: Git-CPAN-Patch 23 | provides: 24 | Git::CPAN::Patch: 25 | file: lib/Git/CPAN/Patch.pm 26 | version: v2.5.0 27 | Git::CPAN::Patch::Command::Clone: 28 | file: lib/Git/CPAN/Patch/Command/Clone.pm 29 | version: v2.5.0 30 | Git::CPAN::Patch::Command::FormatPatch: 31 | file: lib/Git/CPAN/Patch/Command/FormatPatch.pm 32 | version: v2.5.0 33 | Git::CPAN::Patch::Command::Import: 34 | file: lib/Git/CPAN/Patch/Command/Import.pm 35 | version: v2.5.0 36 | Git::CPAN::Patch::Command::SendEmail: 37 | file: lib/Git/CPAN/Patch/Command/SendEmail.pm 38 | version: v2.5.0 39 | Git::CPAN::Patch::Command::SendPatch: 40 | file: lib/Git/CPAN/Patch/Command/SendPatch.pm 41 | version: v2.5.0 42 | Git::CPAN::Patch::Command::Sources: 43 | file: lib/Git/CPAN/Patch/Command/Sources.pm 44 | version: v2.5.0 45 | Git::CPAN::Patch::Command::Squash: 46 | file: lib/Git/CPAN/Patch/Command/Squash.pm 47 | version: v2.5.0 48 | Git::CPAN::Patch::Command::Update: 49 | file: lib/Git/CPAN/Patch/Command/Update.pm 50 | version: v2.5.0 51 | Git::CPAN::Patch::Command::Which: 52 | file: lib/Git/CPAN/Patch/Command/Which.pm 53 | version: v2.5.0 54 | Git::CPAN::Patch::Import: 55 | file: lib/Git/CPAN/Patch/Import.pm 56 | version: v2.5.0 57 | Git::CPAN::Patch::Release: 58 | file: lib/Git/CPAN/Patch/Release.pm 59 | version: v2.5.0 60 | Git::CPAN::Patch::Role::Git: 61 | file: lib/Git/CPAN/Patch/Role/Git.pm 62 | version: v2.5.0 63 | Git::CPAN::Patch::Role::Patch: 64 | file: lib/Git/CPAN/Patch/Role/Patch.pm 65 | version: v2.5.0 66 | requires: 67 | Archive::Any: '0' 68 | Archive::Extract: '0' 69 | BackPAN::Index: '0' 70 | CPAN::Meta: '0' 71 | CPAN::ParseDistribution: '0' 72 | CPANPLUS: '0' 73 | Cwd: '0' 74 | DateTime: '0' 75 | File::Basename: '0' 76 | File::Copy: '0' 77 | File::Find: '0' 78 | File::Path: '0' 79 | File::Spec::Functions: '0' 80 | File::Temp: '0' 81 | File::chdir: '0' 82 | File::chmod: '0' 83 | Git::Repository: '0' 84 | Git::Repository::Plugin::AUTOLOAD: '0' 85 | LWP::Simple: '0' 86 | LWP::UserAgent: '0' 87 | List::Pairwise: '0' 88 | MetaCPAN::API: '0' 89 | MetaCPAN::Client: '0' 90 | Moose: '0' 91 | Moose::Role: '0' 92 | MooseX::App: '1.21' 93 | MooseX::App::Command: '0' 94 | MooseX::App::Role: '0' 95 | MooseX::SemiAffordanceAccessor: '0' 96 | Path::Class: '0' 97 | Path::Tiny: '0' 98 | Pod::Usage: '0' 99 | autodie: '0' 100 | experimental: '0' 101 | perl: v5.20.0 102 | strict: '0' 103 | version: '0' 104 | warnings: '0' 105 | resources: 106 | bugtracker: https://github.com/yanick/git-cpan-patch/issues 107 | homepage: https://github.com/yanick/git-cpan-patch 108 | repository: https://github.com/yanick/git-cpan-patch.git 109 | version: 2.5.0 110 | x_author_pledge: 111 | version: 1 112 | x_authority: cpan:YANICK 113 | x_contributor_covenant: 114 | version: 0.02 115 | x_contributors: 116 | - '2shortplanks ' 117 | - "Arthur Axel 'fREW' Schmidt " 118 | - 'brian d foy ' 119 | - 'chocolateboy ' 120 | - 'Dagfinn Ilmari Mannsåker ' 121 | - 'Graham Knop ' 122 | - 'Lisa Hare ' 123 | - 'Michael G. Schwern ' 124 | - 'Mike Doherty ' 125 | - 'Mike Doherty ' 126 | - 'Pedro Melo ' 127 | - 'Peter Valdemar Mørch ' 128 | - 'Reini Urban ' 129 | - 'sdeseille ' 130 | - 'Slaven Rezic ' 131 | - 'Stefan Hornburg (Racke) ' 132 | - 'temp0 ' 133 | - 'Tim Bunce via RT ' 134 | - 'Yanick Champoux ' 135 | - 'Yuval Kogman ' 136 | - 'Zakariyya Mughal ' 137 | x_generated_by_perl: v5.30.0 138 | x_serialization_backend: 'YAML::Tiny version 1.73' 139 | x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later' 140 | -------------------------------------------------------------------------------- /Makefile.PL: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.017. 2 | use strict; 3 | use warnings; 4 | 5 | use 5.020000; 6 | 7 | use ExtUtils::MakeMaker; 8 | 9 | my %WriteMakefileArgs = ( 10 | "ABSTRACT" => "Patch CPAN modules using Git", 11 | "AUTHOR" => "Yanick Champoux ", 12 | "CONFIGURE_REQUIRES" => { 13 | "ExtUtils::MakeMaker" => 0 14 | }, 15 | "DISTNAME" => "Git-CPAN-Patch", 16 | "EXE_FILES" => [ 17 | "bin/git-cpan" 18 | ], 19 | "LICENSE" => "perl", 20 | "MIN_PERL_VERSION" => "5.020000", 21 | "NAME" => "Git::CPAN::Patch", 22 | "PREREQ_PM" => { 23 | "Archive::Any" => 0, 24 | "Archive::Extract" => 0, 25 | "BackPAN::Index" => 0, 26 | "CPAN::Meta" => 0, 27 | "CPAN::ParseDistribution" => 0, 28 | "CPANPLUS" => 0, 29 | "Cwd" => 0, 30 | "DateTime" => 0, 31 | "File::Basename" => 0, 32 | "File::Copy" => 0, 33 | "File::Find" => 0, 34 | "File::Path" => 0, 35 | "File::Spec::Functions" => 0, 36 | "File::Temp" => 0, 37 | "File::chdir" => 0, 38 | "File::chmod" => 0, 39 | "Git::Repository" => 0, 40 | "Git::Repository::Plugin::AUTOLOAD" => 0, 41 | "LWP::Simple" => 0, 42 | "LWP::UserAgent" => 0, 43 | "List::Pairwise" => 0, 44 | "MetaCPAN::API" => 0, 45 | "MetaCPAN::Client" => 0, 46 | "Moose" => 0, 47 | "Moose::Role" => 0, 48 | "MooseX::App" => "1.21", 49 | "MooseX::App::Command" => 0, 50 | "MooseX::App::Role" => 0, 51 | "MooseX::SemiAffordanceAccessor" => 0, 52 | "Path::Class" => 0, 53 | "Path::Tiny" => 0, 54 | "Pod::Usage" => 0, 55 | "autodie" => 0, 56 | "experimental" => 0, 57 | "strict" => 0, 58 | "version" => 0, 59 | "warnings" => 0 60 | }, 61 | "TEST_REQUIRES" => { 62 | "Carp" => 0, 63 | "DDP" => 0, 64 | "ExtUtils::MakeMaker" => 0, 65 | "File::Spec" => 0, 66 | "IO::Handle" => 0, 67 | "IPC::Open3" => 0, 68 | "Test::MockObject" => 0, 69 | "Test::More" => 0 70 | }, 71 | "VERSION" => "2.5.0", 72 | "test" => { 73 | "TESTS" => "t/*.t" 74 | } 75 | ); 76 | 77 | 78 | my %FallbackPrereqs = ( 79 | "Archive::Any" => 0, 80 | "Archive::Extract" => 0, 81 | "BackPAN::Index" => 0, 82 | "CPAN::Meta" => 0, 83 | "CPAN::ParseDistribution" => 0, 84 | "CPANPLUS" => 0, 85 | "Carp" => 0, 86 | "Cwd" => 0, 87 | "DDP" => 0, 88 | "DateTime" => 0, 89 | "ExtUtils::MakeMaker" => 0, 90 | "File::Basename" => 0, 91 | "File::Copy" => 0, 92 | "File::Find" => 0, 93 | "File::Path" => 0, 94 | "File::Spec" => 0, 95 | "File::Spec::Functions" => 0, 96 | "File::Temp" => 0, 97 | "File::chdir" => 0, 98 | "File::chmod" => 0, 99 | "Git::Repository" => 0, 100 | "Git::Repository::Plugin::AUTOLOAD" => 0, 101 | "IO::Handle" => 0, 102 | "IPC::Open3" => 0, 103 | "LWP::Simple" => 0, 104 | "LWP::UserAgent" => 0, 105 | "List::Pairwise" => 0, 106 | "MetaCPAN::API" => 0, 107 | "MetaCPAN::Client" => 0, 108 | "Moose" => 0, 109 | "Moose::Role" => 0, 110 | "MooseX::App" => "1.21", 111 | "MooseX::App::Command" => 0, 112 | "MooseX::App::Role" => 0, 113 | "MooseX::SemiAffordanceAccessor" => 0, 114 | "Path::Class" => 0, 115 | "Path::Tiny" => 0, 116 | "Pod::Usage" => 0, 117 | "Test::MockObject" => 0, 118 | "Test::More" => 0, 119 | "autodie" => 0, 120 | "experimental" => 0, 121 | "strict" => 0, 122 | "version" => 0, 123 | "warnings" => 0 124 | ); 125 | 126 | 127 | unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { 128 | delete $WriteMakefileArgs{TEST_REQUIRES}; 129 | delete $WriteMakefileArgs{BUILD_REQUIRES}; 130 | $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; 131 | } 132 | 133 | delete $WriteMakefileArgs{CONFIGURE_REQUIRES} 134 | unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; 135 | 136 | WriteMakefile(%WriteMakefileArgs); 137 | -------------------------------------------------------------------------------- /README.mkdn: -------------------------------------------------------------------------------- 1 | # NAME 2 | 3 | Git::CPAN::Patch - Patch CPAN modules using Git 4 | 5 | # VERSION 6 | 7 | version 2.5.0 8 | 9 | # SYNOPSIS 10 | 11 | ```perl 12 | # import a module: 13 | 14 | % git-cpan clone Foo::Bar 15 | % cd Foo-Bar 16 | 17 | # hack and submit to RT 18 | 19 | # it's probably best to work in a branch 20 | % git checkout -b blah 21 | 22 | ... hack lib/Foo/Bar.pm ... 23 | 24 | % git commit -am "blah" 25 | % git-cpan send-patch 26 | 27 | # update the module 28 | # this automatically rebases the current branch 29 | % git-cpan update 30 | ``` 31 | 32 | # DESCRIPTION 33 | 34 | [Git::CPAN::Patch](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch) provides a suite of git commands 35 | aimed at making trivially 36 | easy the process of grabbing 37 | any distribution off CPAN, stuffing it 38 | in a local git repository and, once gleeful 39 | hacking has been perpetrated, sending back 40 | patches to its maintainer. 41 | 42 | NOTE: This module is supported in Linux, BSD, and the like. This 43 | module is **not** supported in Microsoft Windows (Cygwin, Strawberry Perl). 44 | See [CPAN Testers Matrix](http://matrix.cpantesters.org/?dist=Git-CPAN-Patch) 45 | for currently supported operating systems. 46 | 47 | # GIT-CPAN COMMANDS 48 | 49 | - [clone](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3AClone) 50 | 51 | Clone a CPAN module's history into a new git repository 52 | 53 | - [import](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3AImport) 54 | 55 | Import a module into a git repository. 56 | 57 | - [send-email](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3ASendEmail) 58 | 59 | Use `git-send-email` to submit patches to CPAN RT 60 | 61 | - [send-patch](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3ASendPatch) 62 | 63 | Create patch files and submit then to RT 64 | 65 | - [update](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3AUpdate) 66 | 67 | Import the latest version of a module and rebase the current branch 68 | 69 | - [format-patch](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3AFormatPatch) 70 | 71 | Format patches using `cpan/master` as the origin reference 72 | 73 | - [squash](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3ASquash) 74 | 75 | Combine multiple commits into one patch 76 | 77 | - [which](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch%3A%3ACommand%3A%3AWhich) 78 | 79 | Report upon the managed module 80 | 81 | # AUTHORS 82 | 83 | Yanick Champoux `` [![endorse](http://api.coderwall.com/yanick/endorsecount.png)](http://coderwall.com/yanick) 84 | 85 | Yuval Kogman `` 86 | 87 | # SEE ALSO 88 | 89 | ## Articles 90 | 91 | The set of scripts that would eventually become 92 | [Git::CPAN::Patch](https://metacpan.org/pod/Git%3A%3ACPAN%3A%3APatch) were first presented in the 93 | article _CPAN Patching with Git_, published in 94 | issue 5.1 of [The Perl Review](http://theperlreview.com). 95 | 96 | # AUTHOR 97 | 98 | Yanick Champoux [![endorse](http://api.coderwall.com/yanick/endorsecount.png)](http://coderwall.com/yanick) 99 | 100 | # COPYRIGHT AND LICENSE 101 | 102 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 103 | 104 | This is free software; you can redistribute it and/or modify it under 105 | the same terms as the Perl 5 programming language system itself. 106 | -------------------------------------------------------------------------------- /SIGNATURE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanick/git-cpan-patch/e52d866aea01a4e7b9df0e6e4efd974e28f694b5/SIGNATURE -------------------------------------------------------------------------------- /bin/git-cpan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | #PODNAME: git-cpan 4 | use Git::CPAN::Patch; 5 | 6 | Git::CPAN::Patch->new_with_command->run; 7 | 8 | __END__ 9 | 10 | =pod 11 | 12 | =encoding UTF-8 13 | 14 | =head1 NAME 15 | 16 | git-cpan 17 | 18 | =head1 VERSION 19 | 20 | version 2.5.0 21 | 22 | =head1 AUTHOR 23 | 24 | Yanick Champoux 25 | 26 | =head1 COPYRIGHT AND LICENSE 27 | 28 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 29 | 30 | This is free software; you can redistribute it and/or modify it under 31 | the same terms as the Perl 5 programming language system itself. 32 | 33 | =cut 34 | -------------------------------------------------------------------------------- /cpanfile: -------------------------------------------------------------------------------- 1 | # This file is generated by Dist::Zilla::Plugin::CPANFile v6.017 2 | # Do not edit this file directly. To change prereqs, edit the `dist.ini` file. 3 | 4 | requires "Archive::Any" => "0"; 5 | requires "Archive::Extract" => "0"; 6 | requires "BackPAN::Index" => "0"; 7 | requires "CPAN::Meta" => "0"; 8 | requires "CPAN::ParseDistribution" => "0"; 9 | requires "CPANPLUS" => "0"; 10 | requires "Cwd" => "0"; 11 | requires "DateTime" => "0"; 12 | requires "File::Basename" => "0"; 13 | requires "File::Copy" => "0"; 14 | requires "File::Find" => "0"; 15 | requires "File::Path" => "0"; 16 | requires "File::Spec::Functions" => "0"; 17 | requires "File::Temp" => "0"; 18 | requires "File::chdir" => "0"; 19 | requires "File::chmod" => "0"; 20 | requires "Git::Repository" => "0"; 21 | requires "Git::Repository::Plugin::AUTOLOAD" => "0"; 22 | requires "LWP::Simple" => "0"; 23 | requires "LWP::UserAgent" => "0"; 24 | requires "List::Pairwise" => "0"; 25 | requires "MetaCPAN::API" => "0"; 26 | requires "MetaCPAN::Client" => "0"; 27 | requires "Moose" => "0"; 28 | requires "Moose::Role" => "0"; 29 | requires "MooseX::App" => "1.21"; 30 | requires "MooseX::App::Command" => "0"; 31 | requires "MooseX::App::Role" => "0"; 32 | requires "MooseX::SemiAffordanceAccessor" => "0"; 33 | requires "Path::Class" => "0"; 34 | requires "Path::Tiny" => "0"; 35 | requires "Pod::Usage" => "0"; 36 | requires "autodie" => "0"; 37 | requires "experimental" => "0"; 38 | requires "perl" => "v5.20.0"; 39 | requires "strict" => "0"; 40 | requires "version" => "0"; 41 | requires "warnings" => "0"; 42 | 43 | on 'test' => sub { 44 | requires "Carp" => "0"; 45 | requires "DDP" => "0"; 46 | requires "ExtUtils::MakeMaker" => "0"; 47 | requires "File::Spec" => "0"; 48 | requires "IO::Handle" => "0"; 49 | requires "IPC::Open3" => "0"; 50 | requires "Test::MockObject" => "0"; 51 | requires "Test::More" => "0"; 52 | }; 53 | 54 | on 'test' => sub { 55 | recommends "CPAN::Meta" => "2.120900"; 56 | }; 57 | 58 | on 'configure' => sub { 59 | requires "ExtUtils::MakeMaker" => "0"; 60 | }; 61 | 62 | on 'configure' => sub { 63 | suggests "JSON::PP" => "2.27300"; 64 | }; 65 | 66 | on 'develop' => sub { 67 | requires "Test::More" => "0.96"; 68 | requires "Test::Vars" => "0"; 69 | }; 70 | -------------------------------------------------------------------------------- /doap.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | Git-CPAN-Patch 10 | Patch CPAN modules using Git 11 | 12 | 13 | Yanick Champoux 14 | 15 | 16 | 17 | 18 | 19 | 2shortplanks 20 | 21 | 22 | 23 | 24 | 25 | Arthur Axel 'fREW' Schmidt 26 | 27 | 28 | 29 | 30 | 31 | brian d foy 32 | 33 | 34 | 35 | 36 | 37 | chocolateboy 38 | 39 | 40 | 41 | 42 | 43 | Dagfinn Ilmari Mannsåker 44 | 45 | 46 | 47 | 48 | 49 | Graham Knop 50 | 51 | 52 | 53 | 54 | 55 | Lisa Hare 56 | 57 | 58 | 59 | 60 | 61 | Michael G. Schwern 62 | 63 | 64 | 65 | 66 | 67 | Mike Doherty 68 | 69 | 70 | 71 | 72 | 73 | Mike Doherty 74 | 75 | 76 | 77 | 78 | 79 | Pedro Melo 80 | 81 | 82 | 83 | 84 | 85 | Peter Valdemar Mørch 86 | 87 | 88 | 89 | 90 | 91 | Reini Urban 92 | 93 | 94 | 95 | 96 | 97 | sdeseille 98 | 99 | 100 | 101 | 102 | 103 | Slaven Rezic 104 | 105 | 106 | 107 | 108 | 109 | Stefan Hornburg 110 | Racke 111 | 112 | 113 | 114 | 115 | 116 | temp0 117 | 118 | 119 | 120 | 121 | 122 | Tim Bunce via RT 123 | 124 | 125 | 126 | 127 | 128 | Yanick Champoux 129 | 130 | 131 | 132 | 133 | 134 | Yuval Kogman 135 | 136 | 137 | 138 | 139 | 140 | Zakariyya Mughal 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 0.0.1 156 | 157 | 158 | 159 | 160 | 0.1.0 161 | 2009-02-02 162 | 163 | 164 | 165 | 166 | 0.1.1 167 | 2009-02-03 168 | 169 | 170 | 171 | 172 | 0.1.2 173 | 2009-02-03 174 | 175 | 176 | 177 | 178 | 0.1.3 179 | 2009-02-05 180 | 181 | 182 | 183 | 184 | 0.1.4 185 | 2009-02-14 186 | 187 | 188 | 189 | 190 | 0.1.5 191 | 2009-03-28 192 | 193 | 194 | 195 | 196 | 0.1.6 197 | 2009-05-12 198 | 199 | 200 | 201 | 202 | 0.1.7 203 | 2009-05-31 204 | 205 | 206 | 207 | 208 | 0.2.0 209 | 2009-07-11 210 | 211 | 212 | 213 | 214 | 0.2.1 215 | 216 | 217 | 218 | 219 | 0.3.0 220 | 2009-12-20 221 | 222 | 223 | 224 | 225 | 0.3.1 226 | 2009-12-20 227 | 228 | 229 | 230 | 231 | 0.3.2 232 | 2010-04-25 233 | 234 | 235 | 236 | 237 | 0.4.0 238 | 2010-06-05 239 | 240 | 241 | 242 | 243 | 0.4.1 244 | 2010-06-06 245 | 246 | 247 | 248 | 249 | 0.4.2 250 | 2010-06-06 251 | 252 | 253 | 254 | 255 | 0.4.3 256 | 2010-06-06 257 | 258 | 259 | 260 | 261 | 0.4.4 262 | 2010-06-07 263 | 264 | 265 | 266 | 267 | 0.4.5 268 | 2010-08-16 269 | 270 | 271 | 272 | 273 | 0.4.6 274 | 2010-10-11 275 | 276 | 277 | 278 | 279 | 0.5.0 280 | 2011-03-05 281 | 282 | 283 | 284 | 285 | 0.6.0 286 | 2011-03-06 287 | 288 | 289 | 290 | 291 | 0.6.1 292 | 2011-06-05 293 | 294 | 295 | 296 | 297 | 0.7.0 298 | 2011-11-12 299 | 300 | 301 | 302 | 303 | 0.8.0 304 | 2012-05-22 305 | 306 | 307 | 308 | 309 | 1.0.0 310 | 2013-01-01 311 | 312 | 313 | 314 | 315 | 1.0.1 316 | 2013-01-01 317 | 318 | 319 | 320 | 321 | 1.0.2 322 | 2013-01-03 323 | 324 | 325 | 326 | 327 | 1.0.3 328 | 2013-01-08 329 | 330 | 331 | 332 | 333 | 1.1.0 334 | 2013-01-19 335 | 336 | 337 | 338 | 339 | 1.1.1 340 | 2013-04-01 341 | 342 | 343 | 344 | 345 | 1.1.2 346 | 2013-04-14 347 | 348 | 349 | 350 | 351 | 1.2.0 352 | 2013-04-21 353 | 354 | 355 | 356 | 357 | 1.2.1 358 | 2013-07-15 359 | 360 | 361 | 362 | 363 | 1.3.0 364 | 2013-07-18 365 | 366 | 367 | 368 | 369 | 1.3.1 370 | 2013-07-27 371 | 372 | 373 | 374 | 375 | 2.0.0 376 | 2014-02-12 377 | 378 | 379 | 380 | 381 | 2.0.1 382 | 2014-02-15 383 | 384 | 385 | 386 | 387 | 2.0.2 388 | 2014-03-03 389 | 390 | 391 | 392 | 393 | 2.0.3 394 | 2014-03-17 395 | 396 | 397 | 398 | 399 | 2.0.4 400 | 2015-04-19 401 | 402 | 403 | 404 | 405 | 2.1.0 406 | 2015-06-01 407 | 408 | 409 | 410 | 411 | 2.2.0 412 | 2015-08-09 413 | 414 | 415 | 416 | 417 | 2.2.1 418 | 2016-02-06 419 | 420 | 421 | 422 | 423 | 2.3.0 424 | 2016-04-13 425 | 426 | 427 | 428 | 429 | 2.3.1 430 | 2017-01-12 431 | 432 | 433 | 434 | 435 | 2.3.2 436 | 2017-12-22 437 | 438 | 439 | 440 | 441 | 2.3.3 442 | 2018-08-21 443 | 444 | 445 | 446 | 447 | 2.3.4 448 | 2018-08-24 449 | 450 | 451 | 452 | 453 | 2.4.0 454 | 2021-09-19 455 | 456 | 457 | Perl 458 | 459 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: Patch CPAN modules using Git 4 | $Git::CPAN::Patch::VERSION = '2.5.0'; 5 | use 5.10.1; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use MooseX::App 1.21; 11 | use MooseX::SemiAffordanceAccessor; 12 | 13 | use MetaCPAN::API; 14 | 15 | app_base 'git-cpan'; 16 | app_namespace 'Git::CPAN::Patch::Command'; 17 | 18 | use experimental qw/ 19 | signatures 20 | postderef 21 | /; 22 | 23 | app_command_name { 24 | join '-', map { lc } $_[0] =~ /([A-Z]+[a-z]+)/g; 25 | }; 26 | 27 | option man => ( 28 | is => 'ro', 29 | isa => 'Bool', 30 | default => 0, 31 | lazy => 1, 32 | trigger => sub { 33 | require Pod::Usage; 34 | my $name = $_[0]->meta->name . '.pm'; 35 | $name =~ s#::#/#g; 36 | 37 | exit Pod::Usage::pod2usage( 38 | -verbose => 2, 39 | -input => $INC{$name} 40 | ); 41 | }, 42 | documentation => q{Prints the command's manpage}, 43 | ); 44 | 45 | has target => ( 46 | is => 'rw', 47 | isa => 'Str', 48 | ); 49 | 50 | has distribution_name => ( 51 | is => 'ro', 52 | lazy_build => 1, 53 | ); 54 | 55 | has distribution_meta => ( 56 | isa => 'HashRef', 57 | is => 'ro', 58 | lazy_build => 1, 59 | ); 60 | 61 | has repo => ( 62 | is => 'ro', 63 | lazy_build => 1, 64 | ); 65 | 66 | sub _build_repo ($self){ 67 | Git::Repository->new( ); 68 | } 69 | 70 | sub _build_distribution_name ($self){ 71 | my $target = $self->target; 72 | 73 | $target =~ s/-/::/g; 74 | 75 | my $mcpan = MetaCPAN::API->new; 76 | 77 | return $mcpan->module( $target )->{distribution}; 78 | } 79 | 80 | sub _build_distribution_meta ($self) { 81 | my $mcpan = MetaCPAN::API->new; 82 | 83 | $mcpan->release( distribution => $self->distribution_name ); 84 | } 85 | 86 | __PACKAGE__->meta->make_immutable; 87 | 88 | 'end of module Git::CPAN::Patch'; 89 | 90 | =pod 91 | 92 | =encoding UTF-8 93 | 94 | =head1 NAME 95 | 96 | Git::CPAN::Patch - Patch CPAN modules using Git 97 | 98 | =head1 VERSION 99 | 100 | version 2.5.0 101 | 102 | =head1 SYNOPSIS 103 | 104 | # import a module: 105 | 106 | % git-cpan clone Foo::Bar 107 | % cd Foo-Bar 108 | 109 | # hack and submit to RT 110 | 111 | # it's probably best to work in a branch 112 | % git checkout -b blah 113 | 114 | ... hack lib/Foo/Bar.pm ... 115 | 116 | % git commit -am "blah" 117 | % git-cpan send-patch 118 | 119 | # update the module 120 | # this automatically rebases the current branch 121 | % git-cpan update 122 | 123 | =head1 DESCRIPTION 124 | 125 | L provides a suite of git commands 126 | aimed at making trivially 127 | easy the process of grabbing 128 | any distribution off CPAN, stuffing it 129 | in a local git repository and, once gleeful 130 | hacking has been perpetrated, sending back 131 | patches to its maintainer. 132 | 133 | NOTE: This module is supported in Linux, BSD, and the like. This 134 | module is B supported in Microsoft Windows (Cygwin, Strawberry Perl). 135 | See L 136 | for currently supported operating systems. 137 | 138 | =head1 GIT-CPAN COMMANDS 139 | 140 | =over 141 | 142 | =item L 143 | 144 | Clone a CPAN module's history into a new git repository 145 | 146 | =item L 147 | 148 | Import a module into a git repository. 149 | 150 | =item L 151 | 152 | Use C to submit patches to CPAN RT 153 | 154 | =item L 155 | 156 | Create patch files and submit then to RT 157 | 158 | =item L 159 | 160 | Import the latest version of a module and rebase the current branch 161 | 162 | =item L 163 | 164 | Format patches using C as the origin reference 165 | 166 | =item L 167 | 168 | Combine multiple commits into one patch 169 | 170 | =item L 171 | 172 | Report upon the managed module 173 | 174 | =back 175 | 176 | =head1 AUTHORS 177 | 178 | Yanick Champoux C<< >> 179 | 180 | Yuval Kogman C<< >> 181 | 182 | =head1 SEE ALSO 183 | 184 | =head2 Articles 185 | 186 | The set of scripts that would eventually become 187 | L were first presented in the 188 | article I, published in 189 | issue 5.1 of L. 190 | 191 | =head1 AUTHOR 192 | 193 | Yanick Champoux 194 | 195 | =head1 COPYRIGHT AND LICENSE 196 | 197 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 198 | 199 | This is free software; you can redistribute it and/or modify it under 200 | the same terms as the Perl 5 programming language system itself. 201 | 202 | =cut 203 | 204 | __END__ 205 | 206 | # TODO add back --compose to sendpatch 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/Clone.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::Clone; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: Clone a CPAN module's history into a new git repository 4 | $Git::CPAN::Patch::Command::Clone::VERSION = '2.5.0'; 5 | use 5.20.0; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use autodie; 11 | use Path::Class; 12 | 13 | use MooseX::App::Command; 14 | extends 'Git::CPAN::Patch::Command::Import'; 15 | 16 | use experimental 'signatures'; 17 | 18 | parameter target => ( 19 | is => 'rw', 20 | isa => 'Str', 21 | required => 0, 22 | ); 23 | 24 | has _seen_imports => ( 25 | is => 'rw', 26 | isa => 'Bool', 27 | default => 0, 28 | ); 29 | 30 | 31 | before [ qw/import_release clone_git_repo /] => sub($self,$release,@) { 32 | return if $self->_seen_imports; 33 | $self->_set_seen_imports(1); 34 | 35 | my $target = $self->target || $release->dist_name; 36 | 37 | say "creating $target"; 38 | 39 | dir($target)->mkpath; 40 | Git::Repository->run( init => $target ); 41 | $self->set_root($target); 42 | }; 43 | 44 | after [ qw/ clone_git_repo import_release /] => sub($self,@) { 45 | $self->git_run( 'reset', '--hard', $self->last_commit ); 46 | }; 47 | 48 | __PACKAGE__->meta->make_immutable; 49 | 50 | 1; 51 | 52 | __END__ 53 | 54 | =pod 55 | 56 | =encoding UTF-8 57 | 58 | =head1 NAME 59 | 60 | Git::CPAN::Patch::Command::Clone - Clone a CPAN module's history into a new git repository 61 | 62 | =head1 VERSION 63 | 64 | version 2.5.0 65 | 66 | =head1 SYNOPSIS 67 | 68 | # from a specific tarball 69 | $ git-cpan clone http://... 70 | $ git-cpan clone /path/to/Foo-Bar-0.03.tar.gz 71 | 72 | # from CPAN, module and dist names are okay 73 | $ git-cpan clone Foo::Bar 74 | $ git-cpan clone Foo-Bar 75 | 76 | # can also specify the directory to create 77 | $ git-cpan clone Foo-Bar my_clone 78 | 79 | =head1 DESCRIPTION 80 | 81 | Clones a CPAN distribution. If a tarball is given, either locally or via an 82 | url, it'll be used. If not, C will try to find the distribution or 83 | module. If it has an official git repository, it'll be cloned. If not, the 84 | history will be created using the CPAN releases. 85 | 86 | If the target 87 | directory is omitted, then the "humanish" part of the distribution is used. 88 | 89 | =head1 AUTHORS 90 | 91 | Mike Doherty C<< >> 92 | 93 | Yanick Champoux C<< >> 94 | 95 | =head1 SEE ALSO 96 | 97 | L, L, L 98 | 99 | =head1 AUTHOR 100 | 101 | Yanick Champoux 102 | 103 | =head1 COPYRIGHT AND LICENSE 104 | 105 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 106 | 107 | This is free software; you can redistribute it and/or modify it under 108 | the same terms as the Perl 5 programming language system itself. 109 | 110 | =cut 111 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/FormatPatch.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::FormatPatch; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: Format patches using C as the origin reference 4 | $Git::CPAN::Patch::Command::FormatPatch::VERSION = '2.5.0'; 5 | use 5.20.0; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | 11 | use MooseX::App::Command; 12 | 13 | with 'Git::CPAN::Patch::Role::Git'; 14 | with 'Git::CPAN::Patch::Role::Patch'; 15 | 16 | use experimental qw/ 17 | signatures 18 | postderef 19 | /; 20 | 21 | 22 | sub run ($self) { $self->format_patch } 23 | 24 | __PACKAGE__->meta->make_immutable; 25 | 26 | 1; 27 | 28 | __END__ 29 | 30 | =pod 31 | 32 | =encoding UTF-8 33 | 34 | =head1 NAME 35 | 36 | Git::CPAN::Patch::Command::FormatPatch - Format patches using C as the origin reference 37 | 38 | =head1 VERSION 39 | 40 | version 2.5.0 41 | 42 | =head1 SYNOPSIS 43 | 44 | % git-cpan format-patch 45 | 46 | =head1 DESCRIPTION 47 | 48 | This is just like running C. 49 | 50 | =head1 AUTHORS 51 | 52 | Yuval Kogman C<< >> 53 | 54 | Yanick Champoux C<< >> 55 | 56 | =head1 SEE ALSO 57 | 58 | L 59 | 60 | L 61 | 62 | =head1 AUTHOR 63 | 64 | Yanick Champoux 65 | 66 | =head1 COPYRIGHT AND LICENSE 67 | 68 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 69 | 70 | This is free software; you can redistribute it and/or modify it under 71 | the same terms as the Perl 5 programming language system itself. 72 | 73 | =cut 74 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/Import.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::Import; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: Import a module into a git repository 4 | $Git::CPAN::Patch::Command::Import::VERSION = '2.5.0'; 5 | use 5.20.0; 6 | 7 | use strict; 8 | use warnings; 9 | use File::Temp qw/ tempdir /; 10 | use Git::Repository; 11 | use Git::CPAN::Patch::Import; 12 | use File::chdir; 13 | use Git::CPAN::Patch::Release; 14 | use Path::Class qw/ dir /; 15 | use MetaCPAN::Client; 16 | 17 | # TODO Path::Class => Path::Tiny 18 | 19 | use MooseX::App::Command; 20 | 21 | extends 'Git::CPAN::Patch'; 22 | with 'Git::CPAN::Patch::Role::Git'; 23 | 24 | has tmpdir => ( 25 | is => 'ro', 26 | isa => 'Path::Tiny', 27 | lazy => 1, 28 | default => sub { 29 | return Path::Tiny->tempdir(); 30 | } 31 | ); 32 | 33 | use experimental qw(smartmatch signatures); 34 | 35 | our $PERL_GIT_URL = 'git://perl5.git.perl.org/perl.git'; 36 | 37 | option 'norepository' => ( 38 | is => 'ro', 39 | isa => 'Bool', 40 | default => 0, 41 | documentation => "don't clone git repository", 42 | ); 43 | 44 | option 'latest' => ( 45 | is => 'ro', 46 | isa => 'Bool', 47 | default => 0, 48 | documentation => 'only pick latest release, if clone from CPAN', 49 | ); 50 | 51 | option check => ( 52 | is => 'ro', 53 | isa => 'Bool', 54 | default => 1, 55 | cmd_negate => 'nocheck', 56 | documentation => q{Verifies that the imported version is greater than what is already imported}, 57 | ); 58 | 59 | option parent => ( 60 | is => 'ro', 61 | isa => 'ArrayRef', 62 | default => sub { [] }, 63 | documentation => q{Parent of the imported release (can have more than one)}, 64 | ); 65 | 66 | parameter thing_to_import => ( 67 | is => 'rw', 68 | isa => 'Str', 69 | required => 0, 70 | ); 71 | 72 | has metacpan => ( 73 | is => 'ro', 74 | default => sub { 75 | MetaCPAN::Client->new; 76 | }, 77 | ); 78 | 79 | option author_name => ( 80 | is => 'ro', 81 | documentation => "explicitly set the author's name", 82 | ); 83 | 84 | option author_email => ( 85 | is => 'ro', 86 | documentation => "explicitly set the author's email", 87 | ); 88 | 89 | sub get_releases_from_url($self,$url) { 90 | require LWP::Simple; 91 | 92 | ( my $name = $url ) =~ s#^.*/##; 93 | my $destination = $self->tmpdir . '/'.$name; 94 | 95 | say "copying '$url' to '$destination'"; 96 | 97 | LWP::Simple::mirror( $url => $destination ) 98 | or die "Failed to mirror $url\n"; 99 | 100 | return Git::CPAN::Patch::Release->new( 101 | metacpan => $self->metacpan, 102 | tarball => $destination 103 | ); 104 | } 105 | 106 | sub get_releases_from_local_file($self,$path) { 107 | return Git::CPAN::Patch::Release->new( metacpan => $self->metacpan, tarball => $path ); 108 | } 109 | 110 | sub clone_git_repo($self,$release,$url) { 111 | $self->git_run( 'remote', 'add', 'cpan', $url ); 112 | { 113 | # git will output the tags on STDERR 114 | local *STDERR; 115 | open STDERR, '>', \my $err; 116 | $self->git_run( 'fetch', 'cpan' ); 117 | say $err; 118 | } 119 | $self->git_run( config => 'cpan.module-name', $release->dist_name ); 120 | } 121 | 122 | sub looks_like_git { 123 | my $repo = shift or return; 124 | 125 | return 1 if $repo->{type} eq 'git'; 126 | 127 | return $repo->{url} =~ /github\.com|\.git$/; 128 | } 129 | 130 | sub get_releases_from_cpan($self,$dist_or_module) { 131 | 132 | # is it a module belonging to a distribution? 133 | my $dist = eval{ $self->metacpan->module($dist_or_module)->data->{distribution} 134 | } || $dist_or_module; 135 | 136 | if ( $dist eq 'perl' ) { 137 | die "$dist_or_module is a core modules, ", 138 | "clone perl from $PERL_GIT_URL instead.\n"; 139 | } 140 | 141 | if( my $latest_release = !$self->norepository && $self->metacpan->release($dist)) { 142 | my $repo = $latest_release->data->{metadata}{resources}{repository}; 143 | if ( looks_like_git($repo) ) { 144 | say "Git repository found: ", $repo->{url}; 145 | $self->clone_git_repo(Git::CPAN::Patch::Release->new( 146 | metacpan => $self->metacpan, 147 | dist_name => $dist, 148 | meta_info => $latest_release, 149 | ),$repo->{url}); 150 | return; 151 | } 152 | } 153 | 154 | if ( $self->latest ) { 155 | my $rel = $self->metacpan->release($dist); 156 | return Git::CPAN::Patch::Release->new( 157 | metacpan => $self->metacpan, 158 | meta_info => $rel->data, 159 | map { $_ => $rel->data->{$_} } qw/ name author date download_url version / 160 | ); 161 | } 162 | 163 | my $releases = $self->metacpan->release( { 164 | distribution => $dist 165 | }) or die "could not find release for '$dist_or_module' on metacpan\n"; 166 | 167 | my @releases; 168 | 169 | while( my $r = $releases->next ) { 170 | push @releases, Git::CPAN::Patch::Release->new( 171 | metacpan => $self->metacpan, 172 | meta_info => $r->data 173 | ); 174 | } 175 | 176 | return sort { $a->date cmp $b->date } @releases; 177 | } 178 | 179 | sub releases_to_import ($self) { 180 | given ( $self->thing_to_import ) { 181 | when ( qr/^(?:https?|file|ftp)::/ ) { 182 | return $self->get_releases_from_url( $_ ); 183 | } 184 | when ( -f $_ ) { 185 | return $self->get_releases_from_local_file( $_ ); 186 | } 187 | default { 188 | return $self->get_releases_from_cpan($_); 189 | } 190 | } 191 | } 192 | 193 | sub import_release($self,$release) { 194 | my $import_version = $release->dist_version; 195 | 196 | if ( $self->check and $self->last_imported_version ) { 197 | return say $release->dist_name . " $import_version has already been imported\n" 198 | if $import_version == $self->last_imported_version; 199 | 200 | return say sprintf "last imported version %s is more recent than %s" 201 | . ", can't import", 202 | $self->last_imported_version, $import_version 203 | if $import_version <= $self->last_imported_version; 204 | } 205 | 206 | # create a tree object for the CPAN module 207 | # this imports the source code without touching the user's working directory or 208 | # index 209 | 210 | my $tree = do { 211 | # don't overwrite the user's index 212 | local $ENV{GIT_INDEX_FILE} = $self->tmpdir . "/temp_git_index"; 213 | local $ENV{GIT_DIR} = dir($self->root . '/.git')->absolute->stringify; 214 | local $ENV{GIT_WORK_TREE} = $release->extracted_dir; 215 | 216 | local $CWD = $release->extracted_dir; 217 | 218 | my $write_tree_repo = Git::Repository->new( work_tree => $CWD ); 219 | 220 | $write_tree_repo->run( qw(add -v --all --force .) ); 221 | $write_tree_repo->run( "write-tree" ); 222 | }; 223 | 224 | # create a commit for the imported tree object and write it into 225 | # refs/heads/cpan/master 226 | { 227 | local %ENV = %ENV; 228 | 229 | # TODO authors and author_date 230 | 231 | # create the commit object 232 | $ENV{GIT_AUTHOR_NAME} = $self->author_name || $release->author_name || $ENV{GIT_AUTHOR_NAME}; 233 | $ENV{GIT_AUTHOR_EMAIL} = $self->author_email || $release->author_email || $ENV{GIT_AUTHOR_EMAIL}; 234 | $ENV{GIT_AUTHOR_DATE} = $release->date if $release->date; 235 | 236 | my @parents = grep { $_ } $self->last_commit, @{ $self->parent }; 237 | 238 | my $message = sprintf "%s %s %s\n", 239 | ( $self->first_import ? 'initial import of' : 'import' ), 240 | $release->dist_name, $release->dist_version; 241 | 242 | no warnings 'uninitialized'; 243 | $message .= <<"END"; 244 | 245 | git-cpan-module: @{[ $release->dist_name ]} 246 | git-cpan-version: @{[ $release->dist_version ]} 247 | git-cpan-authorid: @{[ $release->author_cpan ]} 248 | 249 | END 250 | 251 | my $commit = $self->git_run( 252 | { input => $message }, 253 | 'commit-tree', $tree, map { ( -p => $_ ) } @parents ); 254 | 255 | # finally, update the fake remote branch and create a tag for convenience 256 | 257 | print $self->git_run('update-ref', '-m' => "import " . $release->dist_name, 'refs/remotes/cpan/master', $commit ); 258 | 259 | my $tag_name = $release->dist_version =~ /^v/ ? $release->dist_version : 'v'.$release->dist_version; 260 | print $self->git_run( tag => $tag_name, $commit ); 261 | 262 | say "created tag '@{[ $tag_name ]}' ($commit)"; 263 | } 264 | 265 | $self->git_run( config => 'cpan.module-name', $release->dist_name ); 266 | } 267 | 268 | sub run ($self) { 269 | my @releases = $self->releases_to_import; 270 | 271 | for my $r ( @releases ) { 272 | eval { $self->import_release($r) }; 273 | if ( $@ ) { 274 | warn "failed to import release, skipping...\n$@\n"; 275 | } 276 | } 277 | } 278 | 279 | __PACKAGE__->meta->make_immutable; 280 | 281 | 1; 282 | 283 | __END__ 284 | 285 | =pod 286 | 287 | =encoding UTF-8 288 | 289 | =head1 NAME 290 | 291 | Git::CPAN::Patch::Command::Import - Import a module into a git repository 292 | 293 | =head1 VERSION 294 | 295 | version 2.5.0 296 | 297 | =head1 SYNOPSIS 298 | 299 | # takes any string CPANPLUS handles: 300 | 301 | % git-cpan import Foo::Bar 302 | % git-cpan import A/AU/AUTHORID/Foo-Bar-0.03.tar.gz 303 | % git-cpan import http://backpan.cpan.org/authors/id/A/AU/AUTHORID/Foo-Bar-0.03.tar.gz 304 | 305 | # If the repository is already initialized, can be run with no arguments to 306 | # import the latest version 307 | git-cpan import 308 | 309 | =head1 DESCRIPTION 310 | 311 | This command is used internally by C, C and 312 | C. 313 | 314 | This command takes a tarball, extracts it, and imports it into the repository. 315 | 316 | It is only possible to update to a newer version of a module. 317 | 318 | The module history is tracked in C. 319 | 320 | Tags are created for each version of the module. 321 | 322 | This command does not touch the working directory, and is safe to run even if 323 | you have pending work. 324 | 325 | =head1 OPTIONS 326 | 327 | =over 328 | 329 | =item --check, --nocheck 330 | 331 | Explicitly enables/disables version checking. If version checking is 332 | enabled, which is the default, git-cpan-import will refuse to import a 333 | version of the package 334 | that has a smaller version number than the HEAD of the branch I. 335 | 336 | =item --parent 337 | 338 | Allows adding extra parents when 339 | importing, so that when a patch has been incorporated into an upstream 340 | version the generated commit is like a merge commit, incorporating both 341 | the CPAN history and the user's local history. 342 | 343 | For example, this will set the current HEAD of the master branch as a parent of 344 | the imported CPAN package: 345 | 346 | $ git checkout master 347 | $ git-cpan import --parent HEAD My-Module 348 | 349 | More than one '--parent' can be specified. 350 | 351 | =item --author_name 352 | 353 | Forces the author name to the given value, instead of trying to resolve it from 354 | the release metadata. 355 | 356 | =item --author_email 357 | 358 | Forces the author email to the given value, instead of trying to resolve it from 359 | the release metadata. 360 | 361 | =back 362 | 363 | =head1 AUTHORS 364 | 365 | Yuval Kogman C<< >> 366 | 367 | Yanick Champoux C<< >> 368 | 369 | =head1 SEE ALSO 370 | 371 | L 372 | 373 | =head1 AUTHOR 374 | 375 | Yanick Champoux 376 | 377 | =head1 COPYRIGHT AND LICENSE 378 | 379 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 380 | 381 | This is free software; you can redistribute it and/or modify it under 382 | the same terms as the Perl 5 programming language system itself. 383 | 384 | =cut 385 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/SendEmail.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::SendEmail; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: use C to submit patches to CPAN RT 4 | $Git::CPAN::Patch::Command::SendEmail::VERSION = '2.5.0'; 5 | use 5.10.0; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use MooseX::App::Command; 11 | 12 | with 'Git::CPAN::Patch::Role::Git'; 13 | with 'Git::CPAN::Patch::Role::Patch'; 14 | 15 | parameter extra_arg => ( 16 | is => 'rw', 17 | isa => 'Str', 18 | required => 0, 19 | ); 20 | 21 | sub run { $_[0]->send_emails($_[0]->extra_arg) } 22 | 23 | __PACKAGE__->meta->make_immutable; 24 | 25 | 1; 26 | 27 | __END__ 28 | 29 | =pod 30 | 31 | =encoding UTF-8 32 | 33 | =head1 NAME 34 | 35 | Git::CPAN::Patch::Command::SendEmail - use C to submit patches to CPAN RT 36 | 37 | =head1 VERSION 38 | 39 | version 2.5.0 40 | 41 | =head1 SYNOPSIS 42 | 43 | % git-cpan send_email 44 | 45 | =head1 DESCRIPTION 46 | 47 | This command provides a C<--to> parameter to C that corresponds 48 | to the RT queue of the imported module. 49 | 50 | =head1 AUTHOR 51 | 52 | Yanick Champoux 53 | 54 | =head1 COPYRIGHT AND LICENSE 55 | 56 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 57 | 58 | This is free software; you can redistribute it and/or modify it under 59 | the same terms as the Perl 5 programming language system itself. 60 | 61 | =cut 62 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/SendPatch.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::SendPatch; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: create patch files and submit them to RT 4 | $Git::CPAN::Patch::Command::SendPatch::VERSION = '2.5.0'; 5 | use 5.10.0; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use MooseX::App::Command; 11 | 12 | with 'Git::CPAN::Patch::Role::Git'; 13 | with 'Git::CPAN::Patch::Role::Patch'; 14 | 15 | use experimental qw/ 16 | signatures 17 | postderef 18 | /; 19 | 20 | sub run ($self) { 21 | $self->format_patch; 22 | 23 | if ( $self->nbr_patches > 1 ) { 24 | say "Refusing to send more than one patch (each patch email will be in its own RT ticket)."; 25 | say "Run git-cpan-send-email manually to override, or squash your commits."; 26 | 27 | say and unlink($_) for $self->all_patches; 28 | 29 | return; 30 | } 31 | 32 | $self->send_emails( $self->all_patches ); 33 | } 34 | 35 | __PACKAGE__->meta->make_immutable; 36 | 37 | 1; 38 | 39 | __END__ 40 | 41 | =pod 42 | 43 | =encoding UTF-8 44 | 45 | =head1 NAME 46 | 47 | Git::CPAN::Patch::Command::SendPatch - create patch files and submit them to RT 48 | 49 | =head1 VERSION 50 | 51 | version 2.5.0 52 | 53 | =head1 SYNOPSIS 54 | 55 | % git-cpan send-patch 56 | 57 | =head1 DESCRIPTION 58 | 59 | This command runs C and then if there is one patch file 60 | runs C. 61 | 62 | Multiple patches are not sent because C creates a separate 63 | message for each patch file, resulting in multiple tickets. 64 | 65 | =head1 AUTHOR 66 | 67 | Yanick Champoux 68 | 69 | =head1 COPYRIGHT AND LICENSE 70 | 71 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 72 | 73 | This is free software; you can redistribute it and/or modify it under 74 | the same terms as the Perl 5 programming language system itself. 75 | 76 | =cut 77 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/Sources.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::Sources; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: lists sources for the module 4 | $Git::CPAN::Patch::Command::Sources::VERSION = '2.5.0'; 5 | use 5.10.0; 6 | 7 | use strict; 8 | use warnings; 9 | use List::Pairwise qw/ mapp /; 10 | 11 | use MooseX::App::Command; 12 | 13 | with 'Git::CPAN::Patch::Role::Git'; 14 | 15 | use experimental qw/ 16 | signatures 17 | postderef 18 | /; 19 | 20 | option repository => ( 21 | is => 'rw', 22 | isa => 'Bool', 23 | default => 1, 24 | trigger => sub ($self) { 25 | return unless $self->repository; 26 | $self->set_cpan(0); 27 | $self->set_backpan(0); 28 | }, 29 | documentation => 'show repository information', 30 | ); 31 | 32 | option cpan => ( 33 | is => 'rw', 34 | isa => 'Bool', 35 | default => 1, 36 | trigger => sub ($self) { 37 | return unless $self->cpan; 38 | $self->set_repository(0); 39 | $self->set_backpan(0); 40 | }, 41 | documentation => 'show cpan information', 42 | ); 43 | 44 | option backpan => ( 45 | is => 'rw', 46 | isa => 'Bool', 47 | default => 0, 48 | trigger => sub ($self) { 49 | return unless $self->backpan; 50 | $self->set_repository(0); 51 | $self->set_cpan(0); 52 | }, 53 | documentation => 'show backpan information', 54 | ); 55 | 56 | parameter thingy => ( 57 | is => 'rw', 58 | isa => 'Str', 59 | ); 60 | 61 | has release_meta => ( 62 | is => 'ro', 63 | lazy => 1, 64 | default => sub ($self) { 65 | require MetaCPAN::API; 66 | my $mcpan = MetaCPAN::API->new; 67 | 68 | my $thingy = $self->thingy; 69 | 70 | eval { $mcpan->release( 71 | distribution => $mcpan->module($thingy)->{distribution} 72 | ) } 73 | || eval { $mcpan->release( distribution => $thingy ) } 74 | || die "could not find release for '$thingy' on metacpan\n"; 75 | }, 76 | ); 77 | 78 | has backpan_index => ( 79 | is => 'ro', 80 | lazy => 1, 81 | default => sub { 82 | require BackPAN::Index; 83 | return BackPAN::Index->new; 84 | }, 85 | ); 86 | 87 | sub run ($self) { 88 | if ( $self->repository and $self->release_meta->{resources}{repository} ) { 89 | say "vcs:"; 90 | mapp { say " $a: $b" } %{ $self->release_meta->{resources}{repository} }; 91 | } 92 | 93 | if ( $self->cpan ) { 94 | say "cpan:"; 95 | for ( qw/ download_url / ) { 96 | say " $_: ", $self->release_meta->{$_}; 97 | } 98 | } 99 | 100 | my $BackPAN_URL = "http://backpan.perl.org/"; 101 | if ( $self->backpan ) { 102 | say "backpan:"; 103 | my $dist = $self->backpan_index->dist($self->thingy) 104 | or die "could not find distribution on BackPAN\n"; 105 | 106 | say " - ", $BackPAN_URL . "/" . $_->prefix 107 | for $dist->releases->search( undef, { order_by => "date" } )->all; 108 | } 109 | } 110 | 111 | 112 | __PACKAGE__->meta->make_immutable; 113 | 114 | 1; 115 | 116 | =pod 117 | 118 | =encoding UTF-8 119 | 120 | =head1 NAME 121 | 122 | Git::CPAN::Patch::Command::Sources - lists sources for the module 123 | 124 | =head1 VERSION 125 | 126 | version 2.5.0 127 | 128 | =head1 SYNOPSIS 129 | 130 | % git-cpan sources Foo::Bar 131 | 132 | =head1 AUTHOR 133 | 134 | Yanick Champoux 135 | 136 | =head1 COPYRIGHT AND LICENSE 137 | 138 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 139 | 140 | This is free software; you can redistribute it and/or modify it under 141 | the same terms as the Perl 5 programming language system itself. 142 | 143 | =cut 144 | 145 | __END__ 146 | 147 | 148 | use Moose; 149 | use DateTime::Format::W3CDTF; 150 | 151 | extends 'MooseX::App::Cmd::Command'; 152 | 153 | has '+app' => ( 154 | handles => [ qw/ set_target distribution_meta / ], 155 | ); 156 | 157 | sub execute { 158 | my ( $self, $opts, $args ) = @_; 159 | 160 | die "usage: git-cpan sources \n" unless $args->[0]; 161 | 162 | $self->set_target( $args->[0] ); 163 | my $meta = $self->distribution_meta; 164 | 165 | if ( my $repo = $meta->{resources}{repository} ) { 166 | say "Repository"; 167 | for ( qw/ type url web / ) { 168 | say "\t$_: ", $repo->{$_} if $repo->{$_}; 169 | } 170 | say "\n"; 171 | }; 172 | 173 | say "CPAN"; 174 | my $date = DateTime::Format::W3CDTF->new->parse_datetime( $meta->{date} ); 175 | say "\tlatest release: ", $meta->{version}, " (", $date->ymd, ")"; 176 | say "\turl: ", $meta->{download_url}; 177 | 178 | 179 | } 180 | 181 | 182 | 1; 183 | 184 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/Squash.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::Squash; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: Combine multiple commits into one patch 4 | $Git::CPAN::Patch::Command::Squash::VERSION = '2.5.0'; 5 | use 5.10.0; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use Git::Repository; 11 | 12 | use MooseX::App::Command; 13 | 14 | with 'Git::CPAN::Patch::Role::Git'; 15 | 16 | use experimental qw/ 17 | signatures 18 | postderef 19 | /; 20 | 21 | has first_arg => ( 22 | is => 'ro', 23 | isa => 'Str', 24 | required => 0, 25 | ); 26 | 27 | has branch => ( 28 | is => 'ro', 29 | isa => 'Str', 30 | lazy => 1, 31 | default => sub ($self) { 32 | $self->first_arg || 'patch'; 33 | }, 34 | ); 35 | 36 | sub run ($self) { 37 | my $head = $self->git_run("rev-parse", "--verify", "HEAD"); 38 | 39 | say for $self->git_run("checkout", "-b", $self->branch, "cpan/master"); 40 | 41 | say for $self->git_run("merge", "--squash", $head); 42 | 43 | say ""; 44 | 45 | say "Changes squashed onto working directory, commit and run git-cpan send_patch"; 46 | } 47 | 48 | __PACKAGE__->meta->make_immutable; 49 | 50 | 1; 51 | 52 | __END__ 53 | 54 | =pod 55 | 56 | =encoding UTF-8 57 | 58 | =head1 NAME 59 | 60 | Git::CPAN::Patch::Command::Squash - Combine multiple commits into one patch 61 | 62 | =head1 VERSION 63 | 64 | version 2.5.0 65 | 66 | =head1 SYNOPSIS 67 | 68 | % git-cpan squash temp_submit_branch 69 | 70 | % git commit -m "This is my message" 71 | 72 | % git-cpan send-patch --compose 73 | 74 | # delete the branch now that we're done 75 | % git checkout master 76 | % git branch -D temp_submit_branch 77 | 78 | =head1 DESCRIPTION 79 | 80 | This command creates a new branch from C runs 81 | C against your head revision. This stages all the files for 82 | the branch and allows you to create a combined commit in order to send a single 83 | patch easily. 84 | 85 | =head1 AUTHOR 86 | 87 | Yanick Champoux 88 | 89 | =head1 COPYRIGHT AND LICENSE 90 | 91 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 92 | 93 | This is free software; you can redistribute it and/or modify it under 94 | the same terms as the Perl 5 programming language system itself. 95 | 96 | =cut 97 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/Update.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::Update; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: Import the latest version of a module and rebase the current branch 4 | $Git::CPAN::Patch::Command::Update::VERSION = '2.5.0'; 5 | use 5.10.0; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use Git::Repository; 11 | 12 | use MooseX::App::Command; 13 | 14 | extends 'Git::CPAN::Patch::Command::Import'; 15 | 16 | use experimental qw/ 17 | signatures 18 | postderef 19 | /; 20 | 21 | #TODO check for versions before download 22 | 23 | has last_import_before_run => ( 24 | is => 'rw', 25 | ); 26 | 27 | before run => sub ($self) { 28 | eval { $self->set_last_import_before_run($self->last_commit) } 29 | or die "branch 'cpan/master' doesn't exist yet (import first)\n"; 30 | $self->set_thing_to_import( $self->tracked_distribution ); 31 | }; 32 | 33 | after run => sub ($self) { 34 | return if $self->last_import_before_run eq $self->last_commit; 35 | 36 | $self->git_run( rebase => 'cpan/master' ); 37 | }; 38 | 39 | __PACKAGE__->meta->make_immutable; 40 | 41 | 1; 42 | 43 | __END__ 44 | 45 | =pod 46 | 47 | =encoding UTF-8 48 | 49 | =head1 NAME 50 | 51 | Git::CPAN::Patch::Command::Update - Import the latest version of a module and rebase the current branch 52 | 53 | =head1 VERSION 54 | 55 | version 2.5.0 56 | 57 | =head1 SYNOPSIS 58 | 59 | % git-cpan update 60 | 61 | =head1 DESCRIPTION 62 | 63 | This command runs C, and then if C was updated 64 | runs C, bringing your patches up to date with the 65 | upstream. 66 | 67 | =head1 AUTHORS 68 | 69 | Yuval Kogman C<< >> 70 | 71 | Yanick Champoux C<< >> 72 | 73 | =head1 SEE ALSO 74 | 75 | L, L 76 | 77 | =head1 AUTHOR 78 | 79 | Yanick Champoux 80 | 81 | =head1 COPYRIGHT AND LICENSE 82 | 83 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 84 | 85 | This is free software; you can redistribute it and/or modify it under 86 | the same terms as the Perl 5 programming language system itself. 87 | 88 | =cut 89 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Command/Which.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Command::Which; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: reports the repository's module 4 | $Git::CPAN::Patch::Command::Which::VERSION = '2.5.0'; 5 | use 5.10.0; 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use MooseX::App::Command; 11 | 12 | with 'Git::CPAN::Patch::Role::Git'; 13 | with 'Git::CPAN::Patch::Role::Patch'; 14 | 15 | sub run { say $_[0]->module_name } 16 | 17 | __PACKAGE__->meta->make_immutable; 18 | 19 | 1; 20 | 21 | __END__ 22 | 23 | =pod 24 | 25 | =encoding UTF-8 26 | 27 | =head1 NAME 28 | 29 | Git::CPAN::Patch::Command::Which - reports the repository's module 30 | 31 | =head1 VERSION 32 | 33 | version 2.5.0 34 | 35 | =head1 SYNOPSIS 36 | 37 | % git-cpan which 38 | 39 | =head1 DESCRIPTION 40 | 41 | This command prints the name of the module tracked in C. 42 | 43 | =head1 AUTHORS 44 | 45 | Yanick Champoux C<< >> 46 | 47 | Yuval Kogman C<< >> 48 | 49 | =head1 SEE ALSO 50 | 51 | L 52 | 53 | =head1 AUTHOR 54 | 55 | Yanick Champoux 56 | 57 | =head1 COPYRIGHT AND LICENSE 58 | 59 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 60 | 61 | This is free software; you can redistribute it and/or modify it under 62 | the same terms as the Perl 5 programming language system itself. 63 | 64 | =cut 65 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Import.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Import; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | $Git::CPAN::Patch::Import::VERSION = '2.5.0'; 4 | use 5.10.0; 5 | 6 | use strict; 7 | use warnings; 8 | 9 | { 10 | no warnings; 11 | use 5.010; 12 | 13 | use File::chmod (); # must be before 'autodie' to hush the warnings 14 | 15 | use autodie; 16 | 17 | use Archive::Extract; 18 | $Archive::Extract::PREFER_BIN = 1; 19 | 20 | use File::Find; 21 | use File::Basename; 22 | use File::Spec::Functions; 23 | use File::Temp qw(tempdir); 24 | use File::Path; 25 | use File::chdir; 26 | use Path::Class qw/ file /; 27 | use Cwd qw/ getcwd /; 28 | use version; 29 | use Git::Repository; 30 | use DateTime; 31 | 32 | use CPANPLUS; 33 | use BackPAN::Index; 34 | 35 | } 36 | 37 | our $BackPAN_URL = "http://backpan.perl.org/"; 38 | our $PERL_GIT_URL = 'git://perl5.git.perl.org/perl.git'; 39 | 40 | sub backpan_index { 41 | state $backpan = do { 42 | say "Loading BackPAN index (this may take a while)"; 43 | BackPAN::Index->new; 44 | }; 45 | return $backpan; 46 | } 47 | 48 | sub cpanplus { 49 | state $cpanplus = CPANPLUS::Backend->new; 50 | return $cpanplus; 51 | } 52 | 53 | # Make sure we can read tarballs and change directories 54 | sub _fix_permissions { 55 | my $dir = shift; 56 | 57 | File::chmod::chmod "u+rx", $dir; 58 | find(sub { 59 | -d $_ ? File::chmod::chmod "u+rx", $_ : File::chmod::chmod "u+r", $_; 60 | }, $dir); 61 | } 62 | 63 | sub init_repo { 64 | my $module = shift; 65 | my $opts = shift; 66 | 67 | my $dirname = "."; 68 | if ( defined $opts->{mkdir} ) { 69 | ( $dirname = $opts->{mkdir} || $module ) =~ s/::/-/g; 70 | 71 | if( -d $dirname ) { 72 | die "$dirname already exists\n" unless $opts->{update}; 73 | } 74 | else { 75 | say "creating directory $dirname"; 76 | 77 | # mkpath() does not play nice with overloaded objects 78 | mkpath "$dirname"; 79 | } 80 | } 81 | 82 | { 83 | local $CWD = $dirname; 84 | 85 | if ( -d '.git' ) { 86 | if ( !$opts->{force} and !$opts->{update} ) { 87 | die "Aborting: git repository already present.\n", 88 | "use '--force' if it's really what you want to do\n"; 89 | } 90 | } 91 | else { 92 | Git::Repository->run('init'); 93 | } 94 | } 95 | 96 | return File::Spec->rel2abs($dirname); 97 | } 98 | 99 | 100 | sub releases_in_git { 101 | my $repo = Git::Repository->new; 102 | return unless contains_git_revisions(); 103 | my @releases = map { m{\bgit-cpan-version:\s*(\S+)}x; $1 } 104 | grep /^\s*git-cpan-version:/, 105 | $repo->run(log => '--pretty=format:%b'); 106 | return @releases; 107 | } 108 | 109 | 110 | sub rev_exists { 111 | my $rev = shift; 112 | my $repo = Git::Repository->new; 113 | 114 | return eval { $repo->run( 'rev-parse', $rev ); }; 115 | } 116 | 117 | 118 | sub contains_git_revisions { 119 | return unless -d ".git"; 120 | return rev_exists("HEAD"); 121 | } 122 | 123 | 124 | sub import_one_backpan_release { 125 | my $release = shift; 126 | my $opts = shift; 127 | my $backpan_urls = $opts->{backpan} || $BackPAN_URL; 128 | 129 | # allow multiple backpan URLs to be supplied 130 | $backpan_urls = [ $backpan_urls ] unless (ref($backpan_urls) eq 'ARRAY'); 131 | 132 | my $repo = Git::Repository->new; 133 | 134 | my( $last_commit, $last_version ); 135 | 136 | # figure out if there is already an imported module 137 | if ( $last_commit = eval { $repo->run("rev-parse", "-q", "--verify", "cpan/master") } ) { 138 | $last_version = $repo->run("cpan-last-version"); 139 | } 140 | 141 | my $tmp_dir = File::Temp->newdir( 142 | $opts->{tempdir} ? (DIR => $opts->{tempdir}) : () 143 | ); 144 | 145 | my $archive_file = catfile($tmp_dir, $release->filename); 146 | mkpath dirname $archive_file; 147 | 148 | my $response; 149 | for my $backpan_url (@$backpan_urls) { 150 | my $release_url = $backpan_url . "/" . $release->prefix; 151 | 152 | say "Downloading $release_url"; 153 | $response = get_from_url($release_url, $archive_file); 154 | last if $response->is_success; 155 | 156 | say " failed @{[ $response->status_line ]}"; 157 | } 158 | 159 | if( !$response->is_success ) { 160 | say "Fetch failed. Skipping."; 161 | return; 162 | } 163 | 164 | if( !-e $archive_file ) { 165 | say "$archive_file is missing. Skipping."; 166 | return; 167 | } 168 | 169 | say "extracting distribution"; 170 | my $ae = Archive::Extract->new( archive => $archive_file ); 171 | unless( $ae->extract( to => $tmp_dir ) ) { 172 | say "Couldn't extract $archive_file to $tmp_dir because ".$ae->error; 173 | say "Skipping"; 174 | return; 175 | } 176 | 177 | my $dir = $ae->extract_path; 178 | if( !$dir ) { 179 | say "The archive is empty, skipping"; 180 | return; 181 | } 182 | _fix_permissions($dir); 183 | 184 | my $tree = do { 185 | # don't overwrite the user's index 186 | local $ENV{GIT_INDEX_FILE} = catfile($tmp_dir, "temp_git_index"); 187 | local $ENV{GIT_DIR} = catfile( getcwd(), '.git' ); 188 | local $ENV{GIT_WORK_TREE} = $dir; 189 | 190 | local $CWD = $dir; 191 | 192 | my $write_tree_repo = Git::Repository->new( work_tree => $dir ) ; 193 | 194 | $write_tree_repo->run( qw(add -v --force .) ); 195 | $write_tree_repo->run( "write-tree" ); 196 | }; 197 | 198 | # Create a commit for the imported tree object and write it into 199 | # refs/remotes/cpan/master 200 | local %ENV = %ENV; 201 | $ENV{GIT_AUTHOR_DATE} ||= $release->date; 202 | 203 | my $author = __PACKAGE__->cpanplus->author_tree($release->cpanid); 204 | $ENV{GIT_AUTHOR_NAME} ||= $author->author; 205 | $ENV{GIT_AUTHOR_EMAIL} ||= $author->email; 206 | 207 | my @parents = grep { $_ } $last_commit; 208 | 209 | 210 | # commit message 211 | my $name = $release->dist; 212 | my $version = $release->version || ''; 213 | my $message = join ' ', ( $last_version ? "import" : "initial import of"), "$name $version from CPAN\n"; 214 | $message .= <<"END"; 215 | 216 | git-cpan-module: $name 217 | git-cpan-version: $version 218 | git-cpan-authorid: @{[ $author->cpanid ]} 219 | git-cpan-file: @{[ $release->prefix ]} 220 | 221 | END 222 | 223 | my $commit = $repo->run( { input => $message }, 'commit-tree', $tree, 224 | map { ( -p => $_ ) } @parents ); 225 | 226 | # finally, update the fake branch and create a tag for convenience 227 | my $dist = $release->dist; 228 | print $repo->run('update-ref', '-m' => "import $dist", 'refs/heads/cpan/master', $commit ); 229 | 230 | if( $version ) { 231 | my $tag = $version; 232 | $tag =~ s{^\.}{0.}; # git does not like a leading . as a tag name 233 | $tag =~ s{\.$}{}; # nor a trailing one 234 | if( $repo->run( "tag", "-l" => $tag ) ) { 235 | say "Tag $tag already exists, overwriting"; 236 | } 237 | print $repo->run( "tag", "-f" => $tag, $commit ); 238 | say "created tag '$tag' ($commit)"; 239 | } 240 | } 241 | 242 | 243 | sub get_from_url { 244 | my($url, $file) = @_; 245 | 246 | require LWP::UserAgent; 247 | my $ua = LWP::UserAgent->new; 248 | 249 | my $req = HTTP::Request->new( GET => $url ); 250 | my $res = $ua->request($req, $file); 251 | 252 | return $res; 253 | } 254 | 255 | 256 | sub import_from_backpan { 257 | my ( $distname, $opts ) = @_; 258 | 259 | $distname =~ s/::/-/g; 260 | 261 | # handle --mkdir and raise an error if the target directory has already been git-initialized 262 | my $repo_dir = init_repo($distname, $opts); 263 | 264 | local $CWD = $repo_dir; 265 | 266 | my $backpan = __PACKAGE__->backpan_index; 267 | my $dist = $backpan->dist($distname) 268 | or die "Error: no distributions found. ", 269 | "Are you sure you spelled the module name correctly?\n"; 270 | 271 | fixup_repository(); 272 | 273 | my %existing_releases; 274 | %existing_releases = map { $_ => 1 } releases_in_git() if $opts->{update}; 275 | my $release_added = 0; 276 | for my $release ($dist->releases->search( undef, { order_by => "date" } )) { 277 | next if $existing_releases{$release->version}; 278 | 279 | # skip .ppm files 280 | next if $release->filename =~ m{\.ppm\b}; 281 | 282 | say "importing $release"; 283 | import_one_backpan_release( 284 | $release, 285 | $opts, 286 | ); 287 | $release_added++; 288 | } 289 | 290 | if( !$release_added ) { 291 | if( !keys %existing_releases ) { 292 | say "Empty repository for $dist. Deleting."; 293 | 294 | # We can't delete it if we're inside it. 295 | $CWD = ".."; 296 | rmtree $repo_dir; 297 | 298 | return; 299 | } 300 | else { 301 | say "No updates for $dist."; 302 | return; 303 | } 304 | } 305 | 306 | my $repo = Git::Repository->new; 307 | if( !rev_exists("master") ) { 308 | print $repo->run('checkout', '-t', '-b', 'master', 'cpan/master'); 309 | } 310 | else { 311 | print $repo->run('checkout', 'master', '.'), 312 | $repo->run('merge', 'cpan/master'); 313 | } 314 | 315 | return $repo_dir; 316 | } 317 | 318 | 319 | sub fixup_repository { 320 | my $repo = Git::Repository->new; 321 | 322 | return unless -d ".git"; 323 | 324 | # We do our work in cpan/master, it might not exist if this 325 | # repo was cloned from gitpan. 326 | if( !rev_exists("cpan/master") and rev_exists("master") ) { 327 | print $repo->run('branch', '-t', 'cpan/master', 'master'); 328 | } 329 | } 330 | 331 | use MetaCPAN::API; 332 | my $mcpan = MetaCPAN::API->new; 333 | 334 | sub find_release { 335 | my $input = shift; 336 | 337 | return eval { $mcpan->release( 338 | distribution => $mcpan->module($input)->{distribution} 339 | ) } 340 | || eval { $mcpan->release( distribution => $input ) } 341 | || die "could not find release for '$input' on metacpan\n"; 342 | 343 | } 344 | 345 | sub main { 346 | my $module = shift; 347 | my $opts = shift; 348 | 349 | if ( delete $opts->{backpan} ) { 350 | return import_from_backpan( $module, $opts ); 351 | } 352 | 353 | my $repo = Git::Repository->new; 354 | 355 | my ( $last_commit, $last_version ); 356 | 357 | # figure out if there is already an imported module 358 | if ( $last_commit = eval { $repo->run("rev-parse", "-q", "--verify", "cpan/master") } ) { 359 | $module ||= $repo->run("cpan-which"); 360 | $last_version = $repo->run("cpan-last-version"); 361 | } 362 | 363 | die("Usage: git-cpan import Foo::Bar\n") unless $module; 364 | 365 | # first we figure out a module object from the module argument 366 | 367 | my $release = find_release($module); 368 | 369 | # based on the version number it figured out for us we decide whether or not to 370 | # actually import. 371 | 372 | my $name = $release->{name}; 373 | my $version = $release->{version}; 374 | my $dist = $release->{distribution}; 375 | 376 | if ( $dist eq 'perl' ) { 377 | say "$name is a core modules, ", 378 | "clone perl from $PERL_GIT_URL instead."; 379 | exit; 380 | } 381 | 382 | my $prettyname = $dist . ( " ($module)" x ( $dist ne $module ) ); 383 | 384 | if ( $last_version and $opts->{checkversion} ) { 385 | # if last_version is defined this is an update 386 | my $imported = version->new($last_version); 387 | my $will_import = version->new($release->{version}); 388 | 389 | die "$name has already been imported\n" if $imported == $will_import; 390 | 391 | die "imported version $imported is more recent than $will_import, can't import\n" 392 | if $imported > $will_import; 393 | 394 | say "updating $prettyname from $imported to $will_import"; 395 | 396 | } else { 397 | say "importing $prettyname"; 398 | } 399 | 400 | require LWP::UserAgent; 401 | 402 | my $ua = LWP::UserAgent->new; 403 | 404 | # download the dist and extract into a temporary directory 405 | my $tmp_dir = tempdir( CLEANUP => 0 ); 406 | 407 | say "downloading $dist"; 408 | 409 | my $tarball = file( $tmp_dir, $release->{archive} ); 410 | 411 | $ua->mirror( 412 | $release->{download_url} => $tarball 413 | ) or die "couldn't fetch tarball\n"; 414 | 415 | say "extracting distribution"; 416 | 417 | my $archive = Archive::Extract->new( archive => $tarball ); 418 | $archive->extract( to => $tmp_dir ); 419 | 420 | my $dist_dir = $archive->extract_path 421 | or die "extraction failed\n"; 422 | 423 | # create a tree object for the CPAN module 424 | # this imports the source code without touching the user's working directory or 425 | # index 426 | 427 | my $tree = do { 428 | # don't overwrite the user's index 429 | local $ENV{GIT_INDEX_FILE} = catfile($tmp_dir, "temp_git_index"); 430 | local $ENV{GIT_DIR} = catfile( getcwd(), '.git' ); 431 | local $ENV{GIT_WORK_TREE} = $dist_dir; 432 | 433 | local $CWD = $dist_dir; 434 | 435 | my $write_tree_repo = Git::Repository->new( work_tree => $dist_dir ); 436 | 437 | $write_tree_repo->run( qw(add -v --force .) ); 438 | $write_tree_repo->run( "write-tree" ); 439 | }; 440 | 441 | # create a commit for the imported tree object and write it into 442 | # refs/heads/cpan/master 443 | 444 | { 445 | local %ENV = %ENV; 446 | 447 | my $author_obj = $mcpan->author($release->{author}); 448 | 449 | # try to find a date for the version using the backpan index 450 | # secondly, if the CPANPLUS author object is a fake one (e.g. when importing a 451 | # URI), get the user object by using the ID from the backpan index 452 | unless ( $ENV{GIT_AUTHOR_DATE} ) { 453 | my $mtime = eval { 454 | DateTime->from_epoch( epoch => $release->{stat}{mtime})->ymd; 455 | }; 456 | 457 | warn $@ if $@; 458 | 459 | # CPAN::Checksums makes YYYY-MM-DD dates, but GIT_AUTHOR_DATE 460 | # doesn't support that. 461 | $mtime .= 'T00:00::00' 462 | if $mtime =~ m/\A (\d\d\d\d) - (\d\d?) - (\d\d?) \z/x; 463 | 464 | if ( $mtime ) { 465 | $ENV{GIT_AUTHOR_DATE} = $mtime; 466 | } else { 467 | my %dists; 468 | 469 | if ( $opts->{backpan} ) { 470 | # we need the backpan index for dates 471 | my $backpan = __PACKAGE__->backpan_index; 472 | 473 | %dists = map { $_->filename => $_ } 474 | $backpan->releases($release->{name}); 475 | } 476 | 477 | if ( my $bp_dist = $dists{$dist} ) { 478 | 479 | $ENV{GIT_AUTHOR_DATE} = $bp_dist->date; 480 | 481 | if ( $author_obj->isa("CPANPLUS::Module::Author::Fake") ) { 482 | $author_obj = $mcpan->author_tree($bp_dist->cpanid); 483 | } 484 | } else { 485 | say "Couldn't find upload date for $dist"; 486 | 487 | if ( $author_obj->isa("CPANPLUS::Module::Author::Fake") ) { 488 | say "Couldn't find author for $dist"; 489 | } 490 | } 491 | } 492 | } 493 | 494 | # create the commit object 495 | $ENV{GIT_AUTHOR_NAME} = $author_obj->{name} unless $ENV{GIT_AUTHOR_NAME}; 496 | $ENV{GIT_AUTHOR_EMAIL} = $author_obj->{email}[0] unless $ENV{GIT_AUTHOR_EMAIL}; 497 | 498 | my @parents = ( grep { $_ } $last_commit, @{ $opts->{parent} || [] } ); 499 | 500 | my $message = join ' ', 501 | ( $last_version ? "import" : "initial import of" ), 502 | "$name $version from CPAN\n"; 503 | $message .= <<"END"; 504 | 505 | git-cpan-module: $name 506 | git-cpan-version: $version 507 | git-cpan-authorid: @{[ $author_obj->{pauseid} ]} 508 | 509 | END 510 | 511 | my $commit = $repo->run( 512 | { input => $message }, 513 | 'commit-tree', $tree, map { ( -p => $_ ) } @parents ); 514 | 515 | # finally, update the fake remote branch and create a tag for convenience 516 | 517 | print $repo->run('update-ref', '-m' => "import $dist", 'refs/remotes/cpan/master', $commit ); 518 | 519 | print $repo->run( tag => $version, $commit ); 520 | 521 | say "created tag '$version' ($commit)"; 522 | } 523 | 524 | } 525 | 526 | 1; 527 | 528 | =pod 529 | 530 | =encoding UTF-8 531 | 532 | =head1 NAME 533 | 534 | Git::CPAN::Patch::Import 535 | 536 | =head1 VERSION 537 | 538 | version 2.5.0 539 | 540 | =head1 DESCRIPTION 541 | 542 | This is the guts of Git::CPAN::Patch::Import moved here to make it callable 543 | as a function so git-backpan-init goes faster. 544 | 545 | =head1 NAME 546 | 547 | Git::CPAN::Patch::Import - The meat of git-cpan-import 548 | 549 | =head1 AUTHOR 550 | 551 | Yanick Champoux 552 | 553 | =head1 COPYRIGHT AND LICENSE 554 | 555 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 556 | 557 | This is free software; you can redistribute it and/or modify it under 558 | the same terms as the Perl 5 programming language system itself. 559 | 560 | =cut 561 | 562 | __END__ 563 | 564 | 565 | 1; 566 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Release.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Release; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | $Git::CPAN::Patch::Release::VERSION = '2.5.0'; 4 | use strict; 5 | use warnings; 6 | use File::chdir; 7 | use Archive::Any; 8 | use Path::Tiny; 9 | use File::Temp qw/ tempdir tempfile /; 10 | use version; 11 | 12 | use Moose; 13 | 14 | use experimental qw/ 15 | signatures 16 | postderef 17 | /; 18 | 19 | has tmpdir => ( 20 | is => 'ro', 21 | isa => 'Path::Tiny', 22 | lazy => 1, 23 | default => sub { 24 | return Path::Tiny->tempdir(); 25 | } 26 | ); 27 | 28 | has author_name => ( 29 | is => 'ro', 30 | isa => 'Str', 31 | lazy => 1, 32 | default => sub { 33 | my $self = shift; 34 | 35 | if ( $self->meta_info ) { 36 | my $author = $self->meta_info->{metadata}{author}; 37 | $author = $author->[0] if ref $author; 38 | 39 | if ( !$author or $author eq 'unknown' ) { 40 | $author = $self->meta_info->{author}; 41 | } 42 | 43 | return $author =~ /^\s*(.*?)\s*author_cpan || 'unknown'; 47 | }, 48 | ); 49 | 50 | has author_cpan => ( 51 | is => 'ro', 52 | isa => 'Maybe[Str]', 53 | lazy => 1, 54 | default => sub { 55 | my $author = eval{$_[0]->meta_info->{author}}; 56 | $author = ref $author ? $author->[0] : $author; 57 | $author = uc($1) if $author =~ / ( 63 | is => 'ro', 64 | isa => 'Maybe[Str]', 65 | predicate => 'has_author_email', 66 | lazy => 1, 67 | default => sub { 68 | my $self = shift; 69 | 70 | if ( $self->meta_info ) { 71 | my $author = $self->meta_info->{metadata}{author} || $self->meta_info->{author}; 72 | $author = $author->[0] if ref $author; 73 | return $1 if $author =~ /<(.*?)>\s*$/; 74 | } 75 | return $self->author_cpan . '@cpan.org'; 76 | }, 77 | ); 78 | 79 | sub author_sig { 80 | my $self = shift; 81 | 82 | return sprintf "%s <%s>", $self->author_name, $self->author_email; 83 | } 84 | 85 | has download_url => ( 86 | is => 'ro', 87 | isa => 'Str', 88 | lazy => 1, 89 | default => sub { 90 | my $self = shift; 91 | return $self->meta_info && $self->meta_info->{download_url}; 92 | }, 93 | ); 94 | 95 | has date => ( 96 | is => 'ro', 97 | isa => 'Maybe[Str]', 98 | lazy => 1, 99 | default => sub { 100 | my $self = shift; 101 | return $self->meta_info && $self->meta_info->{date}; 102 | }, 103 | ); 104 | 105 | has version => ( 106 | is => 'ro', 107 | isa => 'Str', 108 | ); 109 | 110 | has tarball => ( 111 | is => 'ro', 112 | isa => 'Str', 113 | lazy => 1, 114 | default => sub { 115 | my $self = shift; 116 | if ( $self->download_url ) { 117 | 118 | my( undef, $file ) = tempfile(); 119 | $file .= ".tar.gz"; 120 | 121 | if ( $self->download_url =~ /^(?:ht|f)tp/ ) { 122 | require LWP::Simple; 123 | LWP::Simple::getstore( $self->download_url => $file ) 124 | or die "could not retrieve ", $self->download_url, "\n"; 125 | } 126 | else { 127 | require File::Copy; 128 | 129 | File::Copy::copy( $self->download_url => $file ); 130 | } 131 | 132 | return $file; 133 | } 134 | 135 | return undef; 136 | }, 137 | ); 138 | 139 | has extracted_dir => ( 140 | is => 'ro', 141 | lazy => 1, 142 | default => sub($self) { 143 | 144 | my $archive = Archive::Any->new( $self->tarball ); 145 | my $tmpdir = $self->tmpdir; 146 | $archive->extract( $tmpdir ); 147 | 148 | return $tmpdir if $archive->is_impolite; 149 | 150 | my $dir; 151 | opendir $dir, $tmpdir; 152 | my( $sub ) = grep { !/^\.\.?$/ } readdir $dir; 153 | 154 | return join '/', $tmpdir, $sub; 155 | }, 156 | ); 157 | 158 | has cpan_parse => ( 159 | is => 'ro', 160 | predicate => 'has_cpan_parse', 161 | lazy => 1, 162 | default => sub($self) { 163 | require CPAN::ParseDistribution; 164 | CPAN::ParseDistribution->new( $self->tarball ); 165 | }, 166 | ); 167 | 168 | has metacpan => ( 169 | is => 'ro', 170 | lazy => 1, 171 | default => sub { 172 | require MetaCPAN::Client; 173 | MetaCPAN::Client->new; 174 | } 175 | ); 176 | 177 | has meta_info => ( 178 | is => 'ro', 179 | lazy => 1, 180 | predicate => 'has_meta_info', 181 | default => sub($self) { 182 | require MetaCPAN::Client; 183 | 184 | if( my $release = $self->metacpan->release({ all => 185 | [ 186 | { distribution => $self->dist_name }, 187 | { version => $self->dist_version }, 188 | ] 189 | }) ) { 190 | $release = $release->next; 191 | return $release->data if $release; 192 | } 193 | 194 | # TODO check on cpan if the info is not there 195 | 196 | require CPAN::Meta; 197 | 198 | my( $result ) = map { CPAN::Meta->load_file($_) } 199 | grep { $_->exists } 200 | map { path( $self->extracted_dir )->child( "META.$_" ) } qw/ json yml /; 201 | 202 | return $result; 203 | 204 | }, 205 | ); 206 | 207 | has dist_version => ( 208 | is => 'ro', 209 | lazy => 1, 210 | default => sub($self) { 211 | $self->has_meta_info 212 | ? $self->meta_info->{version} 213 | : $self->cpan_parse->distversion 214 | }, 215 | ); 216 | 217 | has dist_name => ( 218 | is => 'ro', 219 | lazy => 1, 220 | default => sub($self) { 221 | $self->has_meta_info 222 | ? $self->meta_info->{distribution} || $self->meta_info->{name} 223 | : $self->cpan_parse->dist 224 | ; 225 | }, 226 | ); 227 | 228 | 1; 229 | 230 | __END__ 231 | 232 | =pod 233 | 234 | =encoding UTF-8 235 | 236 | =head1 NAME 237 | 238 | Git::CPAN::Patch::Release 239 | 240 | =head1 VERSION 241 | 242 | version 2.5.0 243 | 244 | =head1 AUTHOR 245 | 246 | Yanick Champoux 247 | 248 | =head1 COPYRIGHT AND LICENSE 249 | 250 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 251 | 252 | This is free software; you can redistribute it and/or modify it under 253 | the same terms as the Perl 5 programming language system itself. 254 | 255 | =cut 256 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Role/Git.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Role::Git; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | #ABSTRACT: provides access to Git repository 4 | $Git::CPAN::Patch::Role::Git::VERSION = '2.5.0'; 5 | use strict; 6 | use warnings; 7 | 8 | use version; 9 | 10 | use Moose::Role; 11 | use MooseX::App::Role; 12 | use MooseX::SemiAffordanceAccessor; 13 | 14 | use Git::Repository; 15 | 16 | use experimental qw/ 17 | signatures 18 | postderef 19 | /; 20 | 21 | option root => ( 22 | is => 'rw', 23 | isa => 'Str', 24 | default => '.' , 25 | documentation => 'Location of the Git repository', 26 | ); 27 | 28 | has git => ( 29 | is => 'ro', 30 | isa => 'Git::Repository', 31 | lazy => 1, 32 | default => sub ($self) { 33 | Git::Repository->new( 34 | work_tree => $self->root 35 | ); 36 | }, 37 | handles => { 38 | git_run => 'run', 39 | }, 40 | ); 41 | 42 | sub last_commit ($self) { 43 | eval { $self->git_run('rev-parse', '--verify', 'cpan/master') } 44 | } 45 | 46 | sub last_imported_version ($self) { 47 | my $last_commit = $self->last_commit or return version->parse(0); 48 | 49 | my $last = join "\n", $self->git_run( log => '--pretty=format:%b', '-n', 1, $last_commit ); 50 | 51 | $last =~ /git-cpan-module:\ (.*?) \s+ git-cpan-version: \s+ (\S+)/sx 52 | or die "Couldn't parse message (not cloned via git cpan import?):\n$last\n"; 53 | 54 | return version->parse($2); 55 | } 56 | 57 | sub tracked_distribution ($self) { 58 | my $last_commit = $self->last_commit or return; 59 | 60 | my $last = join "\n", $self->git_run( log => '--pretty=format:%b', '-n', 1, $last_commit ); 61 | 62 | $last =~ /git-cpan-module:\s+ (.*?) \s+ git-cpan-version: \s+ (\S+)/sx 63 | or die "Couldn't parse message (not cloned via git cpan import?):\n$last\n"; 64 | 65 | return $1; 66 | } 67 | 68 | sub first_import { return !$_[0]->last_commit } 69 | 70 | 1; 71 | 72 | __END__ 73 | 74 | =pod 75 | 76 | =encoding UTF-8 77 | 78 | =head1 NAME 79 | 80 | Git::CPAN::Patch::Role::Git - provides access to Git repository 81 | 82 | =head1 VERSION 83 | 84 | version 2.5.0 85 | 86 | =head1 AUTHOR 87 | 88 | Yanick Champoux 89 | 90 | =head1 COPYRIGHT AND LICENSE 91 | 92 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 93 | 94 | This is free software; you can redistribute it and/or modify it under 95 | the same terms as the Perl 5 programming language system itself. 96 | 97 | =cut 98 | -------------------------------------------------------------------------------- /lib/Git/CPAN/Patch/Role/Patch.pm: -------------------------------------------------------------------------------- 1 | package Git::CPAN::Patch::Role::Patch; 2 | our $AUTHORITY = 'cpan:YANICK'; 3 | $Git::CPAN::Patch::Role::Patch::VERSION = '2.5.0'; 4 | use 5.10.0; 5 | 6 | use strict; 7 | use warnings; 8 | 9 | use Moose::Role; 10 | 11 | use experimental qw/ 12 | signatures 13 | postderef 14 | /; 15 | 16 | requires 'git_run'; 17 | 18 | has patches => ( 19 | is => 'rw', 20 | traits => [ 'Array' ], 21 | isa => 'ArrayRef', 22 | default => sub ($self) { [ 23 | $self->git_run( 'format-patch', 'cpan/master' ) 24 | ] }, 25 | handles => { 26 | add_patches => 'push', 27 | all_patches => 'elements', 28 | nbr_patches => 'count', 29 | }, 30 | ); 31 | 32 | sub format_patch ($self) { 33 | say for $self->all_patches; 34 | } 35 | 36 | has module_name => ( 37 | is => 'ro', 38 | isa => 'Str', 39 | lazy => 1, 40 | default => sub ($self) { 41 | 42 | if (my $module = $self->git->run('config', 'cpan.module-name')) { 43 | return $module 44 | } 45 | 46 | my $last_commit = $self->git->run('rev-parse', '--verify', 'cpan/master'); 47 | 48 | my $last = join "\n", $self->git->run( log => '--pretty=format:%b', '-n', 1, $last_commit ); 49 | 50 | $last =~ /git-cpan-module: \s+ (.*?) \s+ git-cpan-version: \s+ (.*?) \s*$/sx 51 | or die "Couldn't parse message (not cloned via git cpan import?):\n$last\n"; 52 | 53 | $self->git->run('config', 'cpan.module-name', $1); 54 | 55 | return $1; 56 | }, 57 | ); 58 | 59 | sub send_emails($self,@patches) { 60 | my $to = 'bug-' . $self->module_name . '@rt.cpan.org'; 61 | 62 | system 'git', "send-email", '--no-chain-reply-to', "--to", $to, @patches; 63 | } 64 | 65 | 1; 66 | 67 | __END__ 68 | 69 | =pod 70 | 71 | =encoding UTF-8 72 | 73 | =head1 NAME 74 | 75 | Git::CPAN::Patch::Role::Patch 76 | 77 | =head1 VERSION 78 | 79 | version 2.5.0 80 | 81 | =head1 AUTHOR 82 | 83 | Yanick Champoux 84 | 85 | =head1 COPYRIGHT AND LICENSE 86 | 87 | This software is copyright (c) 2022, 2021, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009 by Yanick Champoux. 88 | 89 | This is free software; you can redistribute it and/or modify it under 90 | the same terms as the Perl 5 programming language system itself. 91 | 92 | =cut 93 | -------------------------------------------------------------------------------- /t/00-compile.t: -------------------------------------------------------------------------------- 1 | use 5.006; 2 | use strict; 3 | use warnings; 4 | 5 | # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058 6 | 7 | use Test::More; 8 | 9 | plan tests => 15 + ($ENV{AUTHOR_TESTING} ? 1 : 0); 10 | 11 | my @module_files = ( 12 | 'Git/CPAN/Patch.pm', 13 | 'Git/CPAN/Patch/Command/Clone.pm', 14 | 'Git/CPAN/Patch/Command/FormatPatch.pm', 15 | 'Git/CPAN/Patch/Command/Import.pm', 16 | 'Git/CPAN/Patch/Command/SendEmail.pm', 17 | 'Git/CPAN/Patch/Command/SendPatch.pm', 18 | 'Git/CPAN/Patch/Command/Sources.pm', 19 | 'Git/CPAN/Patch/Command/Squash.pm', 20 | 'Git/CPAN/Patch/Command/Update.pm', 21 | 'Git/CPAN/Patch/Command/Which.pm', 22 | 'Git/CPAN/Patch/Import.pm', 23 | 'Git/CPAN/Patch/Release.pm', 24 | 'Git/CPAN/Patch/Role/Git.pm', 25 | 'Git/CPAN/Patch/Role/Patch.pm' 26 | ); 27 | 28 | my @scripts = ( 29 | 'bin/git-cpan' 30 | ); 31 | 32 | # no fake home requested 33 | 34 | my @switches = ( 35 | -d 'blib' ? '-Mblib' : '-Ilib', 36 | ); 37 | 38 | use File::Spec; 39 | use IPC::Open3; 40 | use IO::Handle; 41 | 42 | open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; 43 | 44 | my @warnings; 45 | for my $lib (@module_files) 46 | { 47 | # see L 48 | my $stderr = IO::Handle->new; 49 | 50 | diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } 51 | $^X, @switches, '-e', "require q[$lib]")) 52 | if $ENV{PERL_COMPILE_TEST_DEBUG}; 53 | 54 | my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]"); 55 | binmode $stderr, ':crlf' if $^O eq 'MSWin32'; 56 | my @_warnings = <$stderr>; 57 | waitpid($pid, 0); 58 | is($?, 0, "$lib loaded ok"); 59 | 60 | shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ 61 | and not eval { +require blib; blib->VERSION('1.01') }; 62 | 63 | if (@_warnings) 64 | { 65 | warn @_warnings; 66 | push @warnings, @_warnings; 67 | } 68 | } 69 | 70 | foreach my $file (@scripts) 71 | { SKIP: { 72 | open my $fh, '<', $file or warn("Unable to open $file: $!"), next; 73 | my $line = <$fh>; 74 | 75 | close $fh and skip("$file isn't perl", 1) unless $line =~ /^#!\s*(?:\S*perl\S*)((?:\s+-\w*)*)(?:\s*#.*)?$/; 76 | @switches = (@switches, split(' ', $1)) if $1; 77 | 78 | close $fh and skip("$file uses -T; not testable with PERL5LIB", 1) 79 | if grep { $_ eq '-T' } @switches and $ENV{PERL5LIB}; 80 | 81 | my $stderr = IO::Handle->new; 82 | 83 | diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } 84 | $^X, @switches, '-c', $file)) 85 | if $ENV{PERL_COMPILE_TEST_DEBUG}; 86 | 87 | my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-c', $file); 88 | binmode $stderr, ':crlf' if $^O eq 'MSWin32'; 89 | my @_warnings = <$stderr>; 90 | waitpid($pid, 0); 91 | is($?, 0, "$file compiled ok"); 92 | 93 | shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ 94 | and not eval { +require blib; blib->VERSION('1.01') }; 95 | 96 | # in older perls, -c output is simply the file portion of the path being tested 97 | if (@_warnings = grep { !/\bsyntax OK$/ } 98 | grep { chomp; $_ ne (File::Spec->splitpath($file))[2] } @_warnings) 99 | { 100 | warn @_warnings; 101 | push @warnings, @_warnings; 102 | } 103 | } } 104 | 105 | 106 | 107 | is(scalar(@warnings), 0, 'no warnings found') 108 | or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; 109 | 110 | 111 | -------------------------------------------------------------------------------- /t/00-load.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; # last test to print 5 | 6 | BEGIN { 7 | use_ok 'Git::CPAN::Patch'; 8 | use_ok 'Git::CPAN::Patch::Import'; 9 | } 10 | -------------------------------------------------------------------------------- /t/00-report-prereqs.dd: -------------------------------------------------------------------------------- 1 | do { my $x = { 2 | 'configure' => { 3 | 'requires' => { 4 | 'ExtUtils::MakeMaker' => '0' 5 | }, 6 | 'suggests' => { 7 | 'JSON::PP' => '2.27300' 8 | } 9 | }, 10 | 'develop' => { 11 | 'requires' => { 12 | 'Test::More' => '0.96', 13 | 'Test::Vars' => '0' 14 | } 15 | }, 16 | 'runtime' => { 17 | 'requires' => { 18 | 'Archive::Any' => '0', 19 | 'Archive::Extract' => '0', 20 | 'BackPAN::Index' => '0', 21 | 'CPAN::Meta' => '0', 22 | 'CPAN::ParseDistribution' => '0', 23 | 'CPANPLUS' => '0', 24 | 'Cwd' => '0', 25 | 'DateTime' => '0', 26 | 'File::Basename' => '0', 27 | 'File::Copy' => '0', 28 | 'File::Find' => '0', 29 | 'File::Path' => '0', 30 | 'File::Spec::Functions' => '0', 31 | 'File::Temp' => '0', 32 | 'File::chdir' => '0', 33 | 'File::chmod' => '0', 34 | 'Git::Repository' => '0', 35 | 'Git::Repository::Plugin::AUTOLOAD' => '0', 36 | 'LWP::Simple' => '0', 37 | 'LWP::UserAgent' => '0', 38 | 'List::Pairwise' => '0', 39 | 'MetaCPAN::API' => '0', 40 | 'MetaCPAN::Client' => '0', 41 | 'Moose' => '0', 42 | 'Moose::Role' => '0', 43 | 'MooseX::App' => '1.21', 44 | 'MooseX::App::Command' => '0', 45 | 'MooseX::App::Role' => '0', 46 | 'MooseX::SemiAffordanceAccessor' => '0', 47 | 'Path::Class' => '0', 48 | 'Path::Tiny' => '0', 49 | 'Pod::Usage' => '0', 50 | 'autodie' => '0', 51 | 'experimental' => '0', 52 | 'perl' => 'v5.20.0', 53 | 'strict' => '0', 54 | 'version' => '0', 55 | 'warnings' => '0' 56 | } 57 | }, 58 | 'test' => { 59 | 'recommends' => { 60 | 'CPAN::Meta' => '2.120900' 61 | }, 62 | 'requires' => { 63 | 'Carp' => '0', 64 | 'DDP' => '0', 65 | 'ExtUtils::MakeMaker' => '0', 66 | 'File::Spec' => '0', 67 | 'IO::Handle' => '0', 68 | 'IPC::Open3' => '0', 69 | 'Test::MockObject' => '0', 70 | 'Test::More' => '0' 71 | } 72 | } 73 | }; 74 | $x; 75 | } -------------------------------------------------------------------------------- /t/00-report-prereqs.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.027 7 | 8 | use Test::More tests => 1; 9 | 10 | use ExtUtils::MakeMaker; 11 | use File::Spec; 12 | 13 | # from $version::LAX 14 | my $lax_version_re = 15 | qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? 16 | | 17 | (?:\.[0-9]+) (?:_[0-9]+)? 18 | ) | (?: 19 | v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? 20 | | 21 | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? 22 | ) 23 | )/x; 24 | 25 | # hide optional CPAN::Meta modules from prereq scanner 26 | # and check if they are available 27 | my $cpan_meta = "CPAN::Meta"; 28 | my $cpan_meta_pre = "CPAN::Meta::Prereqs"; 29 | my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic 30 | 31 | # Verify requirements? 32 | my $DO_VERIFY_PREREQS = 1; 33 | 34 | sub _max { 35 | my $max = shift; 36 | $max = ( $_ > $max ) ? $_ : $max for @_; 37 | return $max; 38 | } 39 | 40 | sub _merge_prereqs { 41 | my ($collector, $prereqs) = @_; 42 | 43 | # CPAN::Meta::Prereqs object 44 | if (ref $collector eq $cpan_meta_pre) { 45 | return $collector->with_merged_prereqs( 46 | CPAN::Meta::Prereqs->new( $prereqs ) 47 | ); 48 | } 49 | 50 | # Raw hashrefs 51 | for my $phase ( keys %$prereqs ) { 52 | for my $type ( keys %{ $prereqs->{$phase} } ) { 53 | for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { 54 | $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; 55 | } 56 | } 57 | } 58 | 59 | return $collector; 60 | } 61 | 62 | my @include = qw( 63 | 64 | ); 65 | 66 | my @exclude = qw( 67 | 68 | ); 69 | 70 | # Add static prereqs to the included modules list 71 | my $static_prereqs = do './t/00-report-prereqs.dd'; 72 | 73 | # Merge all prereqs (either with ::Prereqs or a hashref) 74 | my $full_prereqs = _merge_prereqs( 75 | ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), 76 | $static_prereqs 77 | ); 78 | 79 | # Add dynamic prereqs to the included modules list (if we can) 80 | my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; 81 | my $cpan_meta_error; 82 | if ( $source && $HAS_CPAN_META 83 | && (my $meta = eval { CPAN::Meta->load_file($source) } ) 84 | ) { 85 | $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); 86 | } 87 | else { 88 | $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) 89 | $source = 'static metadata'; 90 | } 91 | 92 | my @full_reports; 93 | my @dep_errors; 94 | my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; 95 | 96 | # Add static includes into a fake section 97 | for my $mod (@include) { 98 | $req_hash->{other}{modules}{$mod} = 0; 99 | } 100 | 101 | for my $phase ( qw(configure build test runtime develop other) ) { 102 | next unless $req_hash->{$phase}; 103 | next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); 104 | 105 | for my $type ( qw(requires recommends suggests conflicts modules) ) { 106 | next unless $req_hash->{$phase}{$type}; 107 | 108 | my $title = ucfirst($phase).' '.ucfirst($type); 109 | my @reports = [qw/Module Want Have/]; 110 | 111 | for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { 112 | next if $mod eq 'perl'; 113 | next if grep { $_ eq $mod } @exclude; 114 | 115 | my $file = $mod; 116 | $file =~ s{::}{/}g; 117 | $file .= ".pm"; 118 | my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; 119 | 120 | my $want = $req_hash->{$phase}{$type}{$mod}; 121 | $want = "undef" unless defined $want; 122 | $want = "any" if !$want && $want == 0; 123 | 124 | my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; 125 | 126 | if ($prefix) { 127 | my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); 128 | $have = "undef" unless defined $have; 129 | push @reports, [$mod, $want, $have]; 130 | 131 | if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { 132 | if ( $have !~ /\A$lax_version_re\z/ ) { 133 | push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; 134 | } 135 | elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { 136 | push @dep_errors, "$mod version '$have' is not in required range '$want'"; 137 | } 138 | } 139 | } 140 | else { 141 | push @reports, [$mod, $want, "missing"]; 142 | 143 | if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { 144 | push @dep_errors, "$mod is not installed ($req_string)"; 145 | } 146 | } 147 | } 148 | 149 | if ( @reports ) { 150 | push @full_reports, "=== $title ===\n\n"; 151 | 152 | my $ml = _max( map { length $_->[0] } @reports ); 153 | my $wl = _max( map { length $_->[1] } @reports ); 154 | my $hl = _max( map { length $_->[2] } @reports ); 155 | 156 | if ($type eq 'modules') { 157 | splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; 158 | push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; 159 | } 160 | else { 161 | splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; 162 | push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; 163 | } 164 | 165 | push @full_reports, "\n"; 166 | } 167 | } 168 | } 169 | 170 | if ( @full_reports ) { 171 | diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; 172 | } 173 | 174 | if ( $cpan_meta_error || @dep_errors ) { 175 | diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; 176 | } 177 | 178 | if ( $cpan_meta_error ) { 179 | my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; 180 | diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; 181 | } 182 | 183 | if ( @dep_errors ) { 184 | diag join("\n", 185 | "\nThe following REQUIRED prerequisites were not satisfied:\n", 186 | @dep_errors, 187 | "\n" 188 | ); 189 | } 190 | 191 | pass; 192 | 193 | # vim: ts=4 sts=4 sw=4 et: 194 | -------------------------------------------------------------------------------- /t/clone.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 2; 5 | 6 | use Git::CPAN::Patch::Command::Clone; 7 | use File::Temp qw/ tempdir /; 8 | use Git::Repository 'AUTOLOAD'; 9 | use Test::MockObject; 10 | 11 | my $data = { 12 | name => 'Git-CPAN-Patch', 13 | author => 'YANICK', 14 | date => '2011-03-06T01:02:03', 15 | download_url => './t/corpus/Git-CPAN-Patch-0.4.5.tar.gz', 16 | version => '0.4.4', 17 | }; 18 | 19 | my $metacpan = Test::MockObject->new 20 | ->set_false( 'module' ) 21 | ->mock( 'release', sub { 22 | return Test::MockObject->new->set_always( data => $data ) 23 | if $_[1] eq 'Git-CPAN-Patch'; 24 | 25 | return Test::MockObject->new->set_series( next => 26 | Test::MockObject->new->set_always( data => { 27 | 'status' => 'cpan', 28 | 'distribution' => 'Git-CPAN-Patch', 29 | author => 'YANICK', 30 | date => '2011-03-06T01:02:03', 31 | download_url => './t/corpus/Git-CPAN-Patch-0.4.5.tar.gz', 32 | version => '0.4.4', 33 | metadata => { 34 | 'author' => [ 35 | 'Yanick Champoux ' 36 | ], 37 | }, 38 | })->set_always( meta => { 39 | 'author' => [ 40 | 'Yanick Champoux ' 41 | ], }) 42 | ) if ref $_[1]; 43 | 44 | use Carp; 45 | use DDP; 46 | warn p $_[1]; 47 | confess; 48 | } 49 | ); 50 | 51 | subtest $_ => sub { test_clone($_) } for 52 | qw[ Git-CPAN-Patch ./t/corpus/Git-CPAN-Patch-0.4.5.tar.gz ]; 53 | 54 | sub test_clone { 55 | my $thing = shift; 56 | 57 | plan tests => 7; 58 | 59 | my $root = tempdir( 'repo_XXXX', CLEANUP => 1, DIR => './t' ); 60 | 61 | Git::Repository->run( init => $root ); 62 | my $git = Git::Repository->new( work_tree => $root ); 63 | 64 | note "git directory: $root"; 65 | 66 | my $command = Git::CPAN::Patch::Command::Import->new( 67 | root => $root, 68 | thing_to_import => $thing, 69 | metacpan => $metacpan, 70 | ); 71 | 72 | $command->run; 73 | 74 | like $git->branch( '-a', '--no-color' ) => qr#remotes/cpan/master#, 75 | "branch is there"; 76 | 77 | like $git->tag => qr[v0.4.], "tag is there"; 78 | 79 | my $log = join "\n", $git->log( 'cpan/master' ); 80 | 81 | like $log => qr/Author:\s+Yanick\s+Champoux\s+/, 'author'; 82 | 83 | like $log => qr/initial import of Git-CPAN-Patch 0\.4\./, "main message"; 84 | 85 | like $log => qr/git-cpan-module:\s*Git-CPAN-Patch/, 'git-cpan-module'; 86 | like $log => qr/git-cpan-version:\s*0.4./, 'git-cpan-version'; 87 | like $log => qr/git-cpan-authorid:\s*YANICK/, 'git-cpan-authorid'; 88 | } 89 | -------------------------------------------------------------------------------- /t/corpus/Git-CPAN-Patch-0.4.5.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanick/git-cpan-patch/e52d866aea01a4e7b9df0e6e4efd974e28f694b5/t/corpus/Git-CPAN-Patch-0.4.5.tar.gz -------------------------------------------------------------------------------- /xauth/clone-from-github.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use Git::CPAN::Patch::Command::Clone; 7 | use Path::Tiny; 8 | use Git::Repository; 9 | 10 | my $tmpdir = Path::Tiny->tempdir( path('.')->absolute.'/tmp/XXXXXXXX', CLEANUP => 0, TMPDIR => 0 ); 11 | diag "temp dir: $tmpdir"; 12 | 13 | Git::CPAN::Patch::Command::Clone->new( 14 | target => $tmpdir->stringify, 15 | thing_to_import => 'Git::CPAN::Patch', 16 | )->run; 17 | 18 | my $repo = Git::Repository->new( work_tree => $tmpdir->stringify ); 19 | 20 | my $log = $repo->run( qw/ log -1 / ); 21 | 22 | my %config = ( author_name => 'Yanick Champoux', cpan_id => 'YANICK', ); 23 | 24 | unlike $log => qr/Author:\s+unknown/; 25 | like $log => qr/Author:\s+$config{author_name}/; 26 | unlike $log => qr/git-cpan-authorid:\s+unknown/; 27 | like $log => qr/git-cpan-authorid:\s+$config{cpan_id}/; 28 | -------------------------------------------------------------------------------- /xauth/clone-from-module.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More tests => 1; 5 | 6 | use Git::CPAN::Patch::Command::Clone; 7 | use Path::Tiny; 8 | use Git::Repository; 9 | 10 | my %things_to_import = ( 11 | 'Git::CPAN::Patch' => { author_name => 'Yanick Champoux', cpan_id => 'YANICK', }, 12 | # 'CSS-LESSp' => { author_name => 'Ivan Drinchev', cpan_id => 'DRINCHEV', }, 13 | # './t/corpus/Git-CPAN-Patch-0.4.5.tar.gz' => { author_name => 'Yanick Champoux', cpan_id => 'YANICK', }, 14 | # './/t/corpus/Git-CPAN-Patch-0.4.5.tar.gz' => { author_name => 'Yanick Champoux', cpan_id => 'YANICK', }, 15 | ); 16 | 17 | my $here = path('.')->absolute; 18 | use File::chdir; 19 | 20 | while( my( $thing, $config ) = each %things_to_import ) { 21 | subtest $thing => sub { 22 | local $CWD = $here; 23 | 24 | my %config = %$config; 25 | 26 | my $tmpdir = Path::Tiny->tempdir( $here.'/tmp/XXXXXXXX', CLEANUP => 0, TMPDIR => 0 ); 27 | diag "temp dir: $tmpdir"; 28 | 29 | Git::CPAN::Patch::Command::Clone->new( 30 | norepository => 1, 31 | latest => 1, 32 | target => $tmpdir->stringify, 33 | thing_to_import => $thing, 34 | )->run; 35 | 36 | my $repo = Git::Repository->new( work_tree => $tmpdir->stringify ); 37 | 38 | my $log = $repo->run( qw/ log -1 / ); 39 | 40 | unlike $log => qr/Author:\s+unknown/; 41 | like $log => qr/Author:\s+$config{author_name}/; 42 | unlike $log => qr/git-cpan-authorid:\s+unknown/; 43 | like $log => qr/git-cpan-authorid:\s+$config{cpan_id}/; 44 | }; 45 | } 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /xt/release/unused-vars.t: -------------------------------------------------------------------------------- 1 | #!perl 2 | 3 | use Test::More 0.96 tests => 1; 4 | eval { require Test::Vars }; 5 | 6 | SKIP: { 7 | skip 1 => 'Test::Vars required for testing for unused vars' 8 | if $@; 9 | Test::Vars->import; 10 | 11 | subtest 'unused vars' => sub { 12 | all_vars_ok(); 13 | }; 14 | }; 15 | --------------------------------------------------------------------------------