Ver Fonte

fully built the ideal structure, now we need the cloning details

George Baugh há 1 ano atrás
pai
commit
ce56944483
1 ficheiros alterados com 86 adições e 10 exclusões
  1. 86 10
      bin/git-clone-entity

+ 86 - 10
bin/git-clone-entity

@@ -7,7 +7,7 @@ use warnings;
 
 use FindBin::libs;
 
-use List::Util qw{first};
+use List::Util qw{first any uniq};
 use HTTP::Tiny;
 use Config::Simple;
 use Getopt::Long qw{GetOptionsFromArray};
@@ -15,10 +15,15 @@ use Pod::Usage;
 use Pithub;
 use Gogs;
 use Git;
+use Clone qw{clone};
 
 use Term::ReadKey();
 use IO::Interactive::Tiny();
 
+use Data::Dumper;
+$Data::Dumper::Purity=1;
+$Data::Dumper::Deepcopy=1;
+
 =head1 DESCRIPTION
 
 It is a common pattern in organizations to have their own git resources, but mirror everything public on one of the big platforms with network effect.
@@ -149,7 +154,7 @@ Allow insecure mirrors or baseurls.  This is just to prevent footgunning by pass
 
 =head3 create
 
-Automatically create a copy of the repo on the mirror if it doesn't exist.
+Automatically create a copy of the repo on the mirror or baseurl if it doesn't exist.
 
 	--create
 
@@ -237,6 +242,8 @@ sub main {
 		'primary_user=s' => \$options{primary},
 		'primary_org=s'  => \$options{primary_org},
 		'verbose'        => \$options{verbose},
+		'create'         => \$options{create},
+		'sync'           => \$options{sync},
     );
 	$verbose = $options{verbose};
 
@@ -308,7 +315,7 @@ sub main {
 			$clients{$mirror_domain} = $mirror;
 		}
 
-		my @fetched = _fetch_all($mirror, $options{users}, $options{orgs}, \%alias_map, $field_name);
+		my @fetched = _fetch_all($mirror, clone($options{users}), clone($options{orgs}), \%alias_map, $field_name);
         _help(7, "The provided server ($mirror_url) could not list repos!", $cleanup ) unless @fetched;
 
 		# GOGS will list all the repos the user *has access to* not all the ones they own.
@@ -338,19 +345,69 @@ sub main {
 		# Set up the "special" URIs
 		foreach my $remote (qw{origin upstream parent}) {
 			next unless $repo_info->{$remote};
-			$repodata{$repo->{name}}{$remote}{fetch} = $repo_info->{clone_uri} if $repo_info->{is_primary_domain};
+			$repodata{$repo->{name}}{$remote}{fetch} = $repo_info if $repo_info->{is_primary_domain};
 			$repodata{$repo->{name}}{$remote}{push} //= [];
-			push(@{$repodata{$repo->{name}}{$remote}{push}}, $repo_info->{clone_uri});
+			push(@{$repodata{$repo->{name}}{$remote}{push}}, $repo_info);
 		}
 		# Set up the user's remote
-		$repodata{$repo->{name}}{$aliased}{fetch} = $repo_info->{clone_uri} if $repo_info->{is_primary_domain};
+		$repodata{$repo->{name}}{$aliased}{fetch} = $repo_info if $repo_info->{is_primary_domain};
 		$repodata{$repo->{name}}{$aliased}{push} //= [];
-		push(@{$repodata{$repo->{name}}{$aliased}{push}}, $repo_info->{clone_uri});
+		push(@{$repodata{$repo->{name}}{$aliased}{push}}, $repo_info);
+
+	}
+
+	# Remotes which we (probably) ought to have.
+	# Also add in 'me' if it's in the list of users
+	my $add_me = any { $_ eq $options{me} } @{$options{users}};
+	my @known_remotes = (qw{origin upstream parent}, $prime_name);
+	push(@known_remotes, $options{me}) if $add_me;
+	@known_remotes = uniq @known_remotes;
+
+	# TODO build a set of repos we need -- be they either mirrors needing setup or things on mirrors needing to be brought into the fold
+	foreach my $repo (keys(%repodata)) {
+		foreach my $remote (@known_remotes) {
+			my $repository = $repodata{$repo}{$remote} // {};
+			# If we only have the push URI for a mirror, then we don't have it locally
+			if (!exists $repository->{fetch}) {
+				LOG("$repo does not exist at $options{baseurl}");
+				next unless $options{create};
+				my $new_repo = _create_repo( $clients{$primary_domain}, $repo, $primary_domain);
+				$repository->{fetch} = $new_repo;
+				$repository->{push} //= [];
+				push(@{$repository->{push}}, $new_repo);
+			}
+			# If we only have the fetch URI, then we don't have it on the mirrors
+			foreach my $push_repo (@{$options{mirrors}}) {
+				next if $push_repo eq $options{baseurl};
+				my ($push_domain) = $push_repo =~ $domainRipper;
+				next if any { $_->{domain} eq $push_domain } @{$repository->{push}};
+				LOG("Repo $repo does not exist at $push_domain");
+				next unless $options{create};
+				my $new_repo = _create_repo( $clients{$push_domain}, $push_repo, $push_domain );
+				$repository->{push} //= [];
+				push(@{$repository->{push}}, $new_repo);
+			}
+			$repodata{$repo}{$remote} = $repository;
+		}
+	}
+
+	# Now that we have everything created that we want, let's prune the info down
+	foreach my $repo (keys(%repodata)) {
+		foreach my $remote (keys(%{$repodata{$repo}})) {
+			LOG("MAP $repo $remote");
+			my $repository = $repodata{$repo}{$remote};
+			my @push_uris = map { $_->{clone_uri} } @{$repository->{push}};
+			$repository = {
+				fetch => $repository->{fetch}{clone_uri},
+				push  => \@push_uris,
+			};
+			$repodata{$repo}{$remote} = $repository;
+		}
 	}
 
 	$cleanup->();
-	use Data::Dumper;
-	die Dumper(\%repodata);
+	print Dumper(\%repodata);
+	die;
 
 	_clone_repos(%repodata);
 
@@ -359,6 +416,21 @@ sub main {
 	return 0;
 }
 
+sub _create_repo {
+	my ($api, $repo, $domain) =@_;
+	LOG("Creating $repo on $domain");
+	return { 'clone_uri' => "$domain TODO" };
+
+	#TODO check that we haven't already created it
+
+	#my $result = $api->repos->create( data => { name => $repo } );
+	#TODO handle errors
+	#my $new_repo = $result->content();
+
+	#TODO fortify the new repo with the needed infos along the lines of L335
+	#TODO set upstream fork if applicable
+}
+
 sub _clone_repos {
 	my (%repodata) = @_;
 
@@ -407,7 +479,11 @@ sub _fetch_upstream_uri {
 	if ($repo->{fork}) {
 		LOG("Looking up what $repo->{name} was forked from...");
 		my $details = $mirror->repos->get( user => $muser, repo => $repo->{name});
-		_help(9, "Could not fetch repository details for $repo->{name}") unless $details && $details->response->is_success();
+		if (!$details || !$details->response->is_success()) {
+			#LOG("Could not fetch repository details for $repo->{name}, skipping...");
+			#next;
+			_help(9, "Could not fetch repository details for $repo->{name}") unless $details && $details->response->is_success();
+		}
 		my $content = $details->content();
 		$upstream_uri = $content->{parent}{$field_name};
 		_help(10, "Could not discern upstream URI for forked repo $repo->{name}!") unless $upstream_uri;