view release on metacpan or search on metacpan
CONTRIBUTING view on Meta::CPAN
Submitting patches
==================
Thank you for your interest in contributing to this project!
Please **do not** submit a pull request on GitHub. The repository
there is an automated mirror, and I don't develop using GitHub's
platform.
Instead, either
- publish a branch somewhere (a GitHub fork is fine), and e-mail
<spwhitton@spwhitton.name> asking me to merge your branch, possibly
using git-request-pull(1)
- prepare patches with git-format-patch(1), and send them to
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
supports doing this.
- API::GitForge::Role::GitForge::clean_repo(): push the gitforge
branch using Git::Wrapper again.
During early testing, this seemed to hang after pushing to
GitLab installations, but it seems to work well now.
0.002 2020-03-09 12:17:47-07:00 America/Phoenix
- Implement API::GitForge::GitLab::_ensure_repo().
- Add git repo metadata to dist.ini.
- Don't disable merge requests in GitLab clean forks.
Otherwise we can't submit merge requests upstream.
- Code cleanup.
0.001 2020-02-16 16:20:35-07:00 America/Phoenix
- First public release.
DEVELOPER-CERTIFICATE view on Meta::CPAN
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
"Getopt::Long" : "0",
"Git::Wrapper" : "0",
"GitLab::API::v4" : "0",
"Net::GitHub" : "0",
"Role::Tiny" : "0",
"Role::Tiny::With" : "0",
"Term::UI" : "0",
"Try::Tiny" : "0",
"perl" : "5.028",
"strict" : "0",
"subs" : "0",
"warnings" : "0"
}
}
},
"release_status" : "stable",
"resources" : {
"repository" : {
"type" : "git",
"url" : "https://git.spwhitton.name/p5-API-GitForge",
"web" : "https://git.spwhitton.name/p5-API-GitForge"
Getopt::Long: '0'
Git::Wrapper: '0'
GitLab::API::v4: '0'
Net::GitHub: '0'
Role::Tiny: '0'
Role::Tiny::With: '0'
Term::UI: '0'
Try::Tiny: '0'
perl: '5.028'
strict: '0'
subs: '0'
warnings: '0'
resources:
repository: https://git.spwhitton.name/p5-API-GitForge
version: '0.007'
x_generated_by_perl: v5.32.1
x_serialization_backend: 'YAML::Tiny version 1.73'
x_spdx_expression: GPL-3.0-only
Makefile.PL view on Meta::CPAN
"File::Temp" => 0,
"Getopt::Long" => 0,
"Git::Wrapper" => 0,
"GitLab::API::v4" => 0,
"Net::GitHub" => 0,
"Role::Tiny" => 0,
"Role::Tiny::With" => 0,
"Term::UI" => 0,
"Try::Tiny" => 0,
"strict" => 0,
"subs" => 0,
"warnings" => 0
},
"VERSION" => "0.007",
"test" => {
"TESTS" => "t/*.t"
}
);
my %FallbackPrereqs = (
Makefile.PL view on Meta::CPAN
"File::Temp" => 0,
"Getopt::Long" => 0,
"Git::Wrapper" => 0,
"GitLab::API::v4" => 0,
"Net::GitHub" => 0,
"Role::Tiny" => 0,
"Role::Tiny::With" => 0,
"Term::UI" => 0,
"Try::Tiny" => 0,
"strict" => 0,
"subs" => 0,
"warnings" => 0
);
unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
delete $WriteMakefileArgs{TEST_REQUIRES};
delete $WriteMakefileArgs{BUILD_REQUIRES};
$WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
bin/git-clean-forge-fork view on Meta::CPAN
version 0.007
=head1 SYNOPSIS
B<git clean-forge-fork> [B<--upstream=>I<REMOTE>]
=head1 DESCRIPTION
Creates a fork for proposing changes to a project hosted on a git
forge, like GitHub or GitLab. Also configures the fork to make it
obvious that it only exists for submitting changes, so that the fork
clutters up your git forge profile a bit less. Also adds a 'fork'
remote to which you can push your proposed changes.
=head1 OPTIONS
=over 4
=item B<--upstream=>I<REMOTE>
Specify the name of the upstream git remote, i.e., what you want to
lib/API/GitForge.pm view on Meta::CPAN
use API::GitForge::GitLab;
our @EXPORT_OK = qw(new_from_domain forge_access_token remote_forge_info);
our %known_forges = (
"github.com" => "API::GitForge::GitHub",
"salsa.debian.org" => "API::GitForge::GitLab",
);
sub new_from_domain {
my %opts = @_;
croak "unknown domain" unless exists $known_forges{ $opts{domain} };
$known_forges{ $opts{domain} }->new(%opts);
}
sub forge_access_token {
my $domain = shift;
my $root = $ENV{XDG_CONFIG_HOME} || catfile $ENV{HOME}, ".config";
my $file = catfile $root, "gitforge", "access_tokens", $domain;
-e $file and -r _ or croak "$file does not exist or is not readable";
open my $fh, "<", $file or die "failed to open $file for reading: $!";
chomp(my $key = <$fh>);
$key;
}
sub remote_forge_info {
my $remote = shift;
my $git = Git::Wrapper->new(getcwd);
my ($uri) = $git->remote("get-url", $remote);
$uri =~ m#^https?://([^:/@]+)/#
or $uri =~ m#^(?:\w+\@)?([^:/@]+):#
or croak "couldn't determine git forge info from $remote remote";
($1, $');
}
1;
lib/API/GitForge/GitHub.pm view on Meta::CPAN
use strict;
use warnings;
use Role::Tiny::With;
use Carp;
use Net::GitHub;
with "API::GitForge::Role::GitForge";
sub _make_api {
my $self = shift;
my %opts;
$opts{access_token} = $self->{_access_token}
if exists $self->{_access_token};
$self->{_api} = Net::GitHub->new(%opts);
}
sub _ensure_fork {
my ($self, $upstream) = @_;
my ($org, $repo) = _extract_repo($upstream);
my $repos = $self->{_api}->repos;
my $user = $self->{_api}->user->show->{login};
my @user_repos = $repos->list_user($user);
my $repo_exists = sub {
grep { $_->{name} eq $repo } @user_repos;
};
if (&$repo_exists) {
$self->_assert_fork_has_parent($upstream);
} else {
$repos->create_fork($org, $repo);
until (&$repo_exists) {
sleep 5;
@user_repos = $repos->list_user($user);
}
}
return "https://github.com/$user/$repo";
}
sub _assert_fork_has_parent {
my ($self, $upstream) = @_;
my (undef, $repo) = _extract_repo($upstream);
my $user = $self->{_api}->user->show->{login};
my $fork = $self->{_api}->repos->get($user, $repo);
$fork->{parent}{full_name} eq $upstream
or croak
"$user/$repo does not have parent $upstream; don't know what to do";
}
sub _clean_config_repo {
my ($self, $target) = @_;
my ($org, $repo) = _extract_repo($target);
my $repos = $self->{_api}->repos;
$repos->set_default_user_repo($org, $repo);
$repos->update({
name => "$repo",
has_wiki => 0,
has_issues => 0,
has_downloads => 0,
has_pages => 0,
has_projects => 0,
});
}
sub _clean_config_fork {
my ($self, $upstream) = @_;
my (undef, $repo) = _extract_repo($upstream);
my $user = $self->{_api}->user->show->{login};
my $repos = $self->{_api}->repos;
$repos->set_default_user_repo($user, $repo);
$repos->update({
name => "$repo",
homepage => "",
description => "Temporary fork for pull request(s)",
default_branch => "gitforge",
});
$self->_clean_config_repo("$user/$repo");
}
sub _ensure_repo {
my ($self, $target) = @_;
my ($org, $repo) = _extract_repo($target);
my $repos = $self->{_api}->repos;
my $user = $self->{_api}->user->show->{login};
my %create_opts = (name => $repo);
my $list_method;
if ($org eq $user) {
$list_method = "list_user";
} else {
$list_method = "list_org";
$create_opts{org} = $org unless $org eq $user;
}
my @list_repos = $repos->$list_method($org);
my $repo_exists = sub {
grep { $_->{name} eq $repo } @list_repos;
};
unless (&$repo_exists) {
$repos->create(\%create_opts);
until (&$repo_exists) {
sleep 5;
@list_repos = $repos->$list_method($org);
}
}
return "https://github.com/$org/$repo";
}
sub _nuke_fork {
my ($self, $upstream) = @_;
$self->_assert_fork_has_parent($upstream);
my (undef, $repo) = _extract_repo($upstream);
my $user = $self->{_api}->user->show->{login};
$self->{_api}->repos->delete($user, $repo);
}
sub _extract_repo {
$_[0] =~ m#^([^/]+)/(.+)(?:\.git)?$#;
($1, $2);
}
1;
__END__
=pod
lib/API/GitForge/GitLab.pm view on Meta::CPAN
use strict;
use warnings;
use Role::Tiny::With;
use Carp;
use GitLab::API::v4;
with "API::GitForge::Role::GitForge";
sub _make_api {
my $self = shift;
my %opts = (url => "https://" . $self->{_domain} . "/api/v4");
$opts{private_token} = $self->{_access_token}
if exists $self->{_access_token};
$self->{_api} = GitLab::API::v4->new(%opts);
}
sub _ensure_fork {
my ($self, $upstream) = @_;
my ($path, $repo) = _extract_project_id($upstream);
my $user = $self->{_api}->current_user->{username};
my @user_repos;
my $update_user_repos = sub {
@user_repos
= @{ $self->{_api}->projects({ search => "$user/$repo" }) };
};
my $repo_exists = sub {
grep { $_->{path_with_namespace} eq "$user/$repo" } @user_repos;
};
&$update_user_repos;
if (&$repo_exists) {
$self->_assert_fork_has_parent($upstream);
} else {
$self->{_api}->fork_project("$path/$repo");
until (&$repo_exists) {
sleep 5;
&$update_user_repos;
}
}
return "https://" . $self->{_domain} . "/$user/$repo.git";
}
sub _assert_fork_has_parent {
my ($self, $upstream) = @_;
my ($path, $repo) = _extract_project_id($upstream);
my $user = $self->{_api}->current_user->{username};
my $fork = $self->{_api}->project("$user/$repo");
$fork->{forked_from_project}{path_with_namespace} eq $path . "/" . $repo
or croak
"$user/$repo does not have parent $upstream; don't know what to do";
}
sub _clean_config_repo {
my ($self, $target) = @_;
my ($ns, $repo) = _extract_project_id($target);
$self->{_api}->edit_project(
"$ns/$repo",
{
issues_access_level => "disabled",
merge_requests_access_level => "disabled",
});
}
sub _clean_config_fork {
my ($self, $upstream) = @_;
my (undef, $repo) = _extract_project_id($upstream);
my $user = $self->{_api}->current_user->{username};
$self->{_api}->edit_project(
"$user/$repo",
{
default_branch => "gitforge",
description => "Temporary fork for merge request(s)",
issues_access_level => "disabled",
# merge requests have to be enabled in the fork in order
# to submit merge requests to the upstream repo from which
# we forked, it seems
merge_requests_access_level => "enabled",
});
}
sub _ensure_repo {
my ($self, $target) = @_;
my ($ns, $repo) = _extract_project_id($target);
return if $self->{_api}->project($target);
my $namespace = $self->{_api}->namespace($ns)
or croak "invalid project namespace $ns";
$self->{_api}
->create_project({ name => $repo, namespace_id => $namespace->{id} });
}
sub _nuke_fork {
my ($self, $upstream) = @_;
$self->_assert_fork_has_parent($upstream);
my (undef, $repo) = _extract_project_id($upstream);
my $user = $self->{_api}->current_user->{username};
$self->{_api}->delete_project("$user/$repo");
}
sub _ensure_fork_branch_unprotected {
my ($self, $upstream, $branch) = @_;
my (undef, $repo) = _extract_project_id($upstream);
my $user = $self->{_api}->current_user->{username};
return unless $self->{_api}->protected_branch("$user/$repo", $branch);
$self->{_api}->unprotect_branch("$user/$repo", $branch);
}
sub _extract_project_id {
my $project = shift;
$project =~ s#(?:\.git)?/?$##;
$project =~ m#/([^/]+)$#;
($`, $1);
}
1;
__END__
lib/API/GitForge/Role/GitForge.pm view on Meta::CPAN
use warnings;
use Role::Tiny;
use Carp;
use File::Temp qw(tempdir);
use Git::Wrapper;
use File::Spec::Functions qw(catfile);
sub new {
my ($class, %opts) = @_;
croak "need domain!" unless exists $opts{domain};
my %attrs = (_domain => $opts{domain});
$attrs{_access_token} = $opts{access_token} if exists $opts{access_token};
my $self = bless \%attrs => $class;
$self->_make_api;
return $self;
}
sub ensure_repo { shift->_create_repo(@_) }
sub clean_repo {
my ($self, $repo) = @_;
$self->_ensure_repo($repo);
$self->_clean_config_repo($repo);
}
sub ensure_fork { shift->_ensure_fork(@_) }
sub clean_fork {
my $self = shift;
my $fork_uri = $self->_ensure_fork($_[0]);
my $temp = tempdir CLEANUP => 1;
my $git = Git::Wrapper->new($temp);
$git->init;
my @fork_branches
= map { m#refs/heads/#; $' } $git->ls_remote("--heads", $fork_uri);
return $fork_uri if grep /\Agitforge\z/, @fork_branches;
open my $fh, ">", catfile $temp, "README.md";
say $fh "This repository exists only in order to submit pull request(s).";
close $fh;
$git->add("README.md");
$git->commit({ message => "Temporary fork for pull request(s)" });
# We should be able to just say
#
# $git->push($fork_uri, "master:gitforge");
#
# but that hangs indefinitely when pushing to (at least) Debian's
# GitLab instance. So just bypass Git::Wrapper and do the push
lib/API/GitForge/Role/GitForge.pm view on Meta::CPAN
if ($self->can("_ensure_fork_branch_unprotected")) {
$self->_ensure_fork_branch_unprotected($_[0], $_) for @fork_branches;
}
# may fail if we couldn't unprotect; that's okay
eval { $git->push($fork_uri, "--delete", @fork_branches) };
return $fork_uri;
}
sub nuke_fork { shift->_nuke_fork(@_) }
sub clean_config_repo { shift->_clean_config_repo(@_) }
sub clean_config_fork { shift->_clean_config_fork(@_) }
requires
qw<_make_api _ensure_repo _clean_config_repo _clean_config_fork
_ensure_fork _nuke_fork>;
1;
__END__
=pod
lib/API/GitForge/Role/GitForge.pm view on Meta::CPAN
=head2 ensure_fork($upstream)
Ensure that the current user has a fork of the repo at
C<https://example.com/$upstream>, and return URI to that fork suitable
for adding as a git remote.
=head2 clean_fork($upstream)
Ensure that the current user has a fork of the repo at
C<https://example.com/$upstream>, config that fork to make it obvious
it's only there for submitting change proposals, and return URI to
fork suitable for adding as a git remote.
=head2 nuke_fork($upstream)
Delete the user's fork of the repo at
C<https://example.com/$upstream>.
=head2 clean_config_repo($repo)
Turn off optional forge features for repo at
C<https://example.com/$repo>.
=head2 clean_config_fork($upstream)
Configure user's fork of repo at C<https://example.com/$upstream> to
make it obvious that it's only there for submitting change proposals.
=head1 STATUS
Unstable. Interface may change.
=head1 AUTHOR
Sean Whitton <spwhitton@spwhitton.name>
=head1 COPYRIGHT AND LICENSE
lib/App/git/clean_forge_fork.pm view on Meta::CPAN
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
$App::git::clean_forge_fork::VERSION = '0.007';
use 5.028;
use strict;
use warnings;
use subs 'main';
use Term::UI;
use Getopt::Long;
use Git::Wrapper;
use API::GitForge qw(new_from_domain forge_access_token remote_forge_info);
use Try::Tiny;
use Cwd;
my $exit_main = 0;
CORE::exit main unless caller;
sub main {
shift if $_[0] and ref $_[0] eq "";
local @ARGV = @{ $_[0] } if $_[0] and ref $_[0] ne "";
my $term = Term::ReadLine->new("brand");
my $upstream = "origin";
my $git = Git::Wrapper->new(getcwd);
#<<<
try {
$git->rev_parse({ git_dir => 1 });
} catch {
die "pwd doesn't look like a git repository ..\n";
};
#>>>
GetOptions "upstream=s" => \$upstream;
my ($forge_domain, $upstream_repo) = remote_forge_info $upstream;
exit
unless $term->ask_yn(
prompt => "Do you want to submit changes against $upstream_repo?");
my $forge = new_from_domain
domain => $forge_domain,
access_token => forge_access_token $forge_domain;
my $fork_uri = $forge->clean_fork($upstream_repo);
if (grep /\Afork\z/, $git->remote) {
$fork_uri eq ($git->remote(qw(get-url fork)))[0]
or die "fork remote exists but has wrong URI\n";
} else {
$git->remote(qw(add fork), $fork_uri);
}
EXIT_MAIN:
return $exit_main;
}
sub exit { $exit_main = shift // 0; goto EXIT_MAIN }
__END__
=pod
=encoding UTF-8
=head1 NAME
App::git::clean_forge_fork - create tidy forks for pull requests
lib/App/git/clean_forge_repo.pm view on Meta::CPAN
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
$App::git::clean_forge_repo::VERSION = '0.007';
use 5.028;
use strict;
use warnings;
use subs 'main';
use Cwd;
use Term::UI;
use Getopt::Long;
use Git::Wrapper;
use API::GitForge qw(new_from_domain forge_access_token remote_forge_info);
use Try::Tiny;
my $exit_main = 0;
CORE::exit main unless caller;
sub main {
shift if $_[0] and ref $_[0] eq "";
local @ARGV = @{ $_[0] } if $_[0] and ref $_[0] ne "";
my $term = Term::ReadLine->new("brand");
my $remote = "origin";
my $git = Git::Wrapper->new(getcwd);
#<<<
try {
$git->rev_parse({ git_dir => 1 });
} catch {
lib/App/git/clean_forge_repo.pm view on Meta::CPAN
my $forge = new_from_domain
domain => $forge_domain,
access_token => forge_access_token $forge_domain;
$forge->clean_repo($forge_repo);
EXIT_MAIN:
return $exit_main;
}
sub exit { $exit_main = shift // 0; goto EXIT_MAIN }
__END__
=pod
=encoding UTF-8
=head1 NAME
App::git::clean_forge_repo - create repos on git forges with optional features disabled
lib/App/git/nuke_forge_fork.pm view on Meta::CPAN
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
$App::git::nuke_forge_fork::VERSION = '0.007';
use 5.028;
use strict;
use warnings;
use subs 'main';
use Getopt::Long;
use Git::Wrapper;
use API::GitForge qw(new_from_domain forge_access_token remote_forge_info);
use Try::Tiny;
use Cwd;
use Term::UI;
my $exit_main = 0;
CORE::exit main unless caller;
sub main {
shift if $_[0] and ref $_[0] eq "";
local @ARGV = @{ $_[0] } if $_[0] and ref $_[0] ne "";
my $term = Term::ReadLine->new("brand");
my $upstream = "origin";
my $git = Git::Wrapper->new(getcwd);
#<<<
try {
$git->rev_parse({ git_dir => 1 });
} catch {
lib/App/git/nuke_forge_fork.pm view on Meta::CPAN
my $forge = new_from_domain
domain => $forge_domain,
access_token => forge_access_token $forge_domain;
$forge->nuke_fork($upstream_repo);
$git->remote(qw(rm fork));
EXIT_MAIN:
return $exit_main;
}
sub exit { $exit_main = shift // 0; goto EXIT_MAIN }
__END__
=pod
=encoding UTF-8
=head1 NAME
App::git::nuke_forge_fork - delete forks created by git-clean-forge-fork(1)