Parcourir la source

data structure looking right now

George Baugh il y a 1 an
Parent
commit
3aba66427f
1 fichiers modifiés avec 64 ajouts et 8 suppressions
  1. 64 8
      bin/git-clone-entity

+ 64 - 8
bin/git-clone-entity

@@ -7,6 +7,7 @@ use warnings;
 
 use FindBin::libs;
 
+use List::Util qw{first};
 use HTTP::Tiny;
 use Config::Simple;
 use Getopt::Long qw{GetOptionsFromArray};
@@ -27,11 +28,11 @@ Alternatively, you may just want to keep your local development environment up t
 
 This program facilitiates cloning your repositories for given users/orgs from either a local gogs/github instance and configuring pushurls for both it and github, or any other github-api compatible mirror(s).
 
-By default it will configure your origin remote to fetch from the baseurl provided, and push to it and the mirror(s) provided, but you can specify whatever remotename ('all' seems popular) you desire.
+It will configure your 'origin' & 'upstream' remote to fetch from the baseurl provided, and push to it and the mirror(s) provided.
 Regardless, remotes for the base and mirrors will also be set up in case individual pushes must be made.
 
-In the event that two different users/orgs have the same named repository (e.g. forks) it will .
-Will set up remotes named after the user/org in the event the repo is a fork, and set the 'upstream' name to be the parent repository.
+In the event that two different users/orgs have the same named repository (e.g. forks) it
+will set up remotes named after the user/org in the event the repo is a fork, and set the 'upstream' name to be the parent repository.
 This will not recursively scan for the oldest ancestor as parent; most of the time that's a bad idea.
 
 In the event that all the copies of a repo happen to be a fork on the passed users/orgs,
@@ -70,6 +71,8 @@ git clone-entity --user $user1 --user $user2 --org $org1 --org $org2 --alias $us
 
 Your username on the baseurl.  Relevant to token use, what is visible, etc.
 
+In the event your username is also having it's repos cloned, your remotes will become 'origin', otherwise the 'primary_user' or 'primary_org' will.
+
 	--me tarzan
 
 =head3 baseurl
@@ -97,7 +100,7 @@ You can omit the auth token on gogs, as we can create them automatically (we wil
 
 Primary entity to clone.  Consider their repository to be the canonical one.  One or the other must be passed.  In the event both are, the org is preferred.
 
-In most organizations, you will have the org hold the primary copy of a repo, with developers forking copies.
+In most organizations, you will have the org hold the primary copy of a repo, with developers forking copies.  This will become the "upstream" remote.
 
 	--primary_org 'BigHugsLLC'
 
@@ -315,34 +318,87 @@ sub main {
     }
 
     my ($primary_domain) = $options{baseurl} =~ $domainRipper;
+	my $cloning_myself = first { $_ eq $options{me} } (@{$options{users}},@{$options{orgs}});
 
 	my %repodata;
 	foreach my $repo (@repos) {
-		$repodata{$repo->{name}} //= [];
+		$repodata{$repo->{name}} //= {};
 		my $reversed = $alias_reverse{$repo->{domain}} // {};
 		my $aliased = exists $reversed->{$repo->{owner}{login}} ? $reversed->{$repo->{owner}{login}} : $repo->{owner}{login};
 		my $repo_info = {
 			clone_uri           => $repo->{$field_name},
-			upstream_uri        => $repo->{upstream_uri},
+			parent              => $repo->{upstream_uri},
 			private             => $repo->{private},
 			is_primary_domain   => $repo->{domain} eq $primary_domain,
 			domain              => $repo->{domain},
-			is_primary_owner    => $aliased eq $prime_name,
+			upstream            => $aliased eq $prime_name,
 			owner               => $aliased,
+			origin              => $aliased eq $options{me} || ( !$cloning_myself && $aliased eq $prime_name ),
 		};
-		push(@{$repodata{$repo->{name}}}, $repo_info);
+		# 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}{push} //= [];
+			push(@{$repodata{$repo->{name}}{$remote}{push}}, $repo_info->{clone_uri});
+		}
+		# 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}{push} //= [];
+		push(@{$repodata{$repo->{name}}{$aliased}{push}}, $repo_info->{clone_uri});
 	}
 
 	$cleanup->();
 	use Data::Dumper;
 	die Dumper(\%repodata);
 
+	_clone_repos(%repodata);
+
 	# Clean up
 	$cleanup->();
 	return 0;
 }
 
 sub _clone_repos {
+	my (%repodata) = @_;
+
+	foreach my $to_clone (keys(%repodata)) {
+		#XXX testing removme
+		next unless $to_clone eq 'perl-Gogs';
+
+		my $r = $repodata{$to_clone};
+
+		# Don't clone it if it is already present.
+		if (!-d $to_clone) {
+			LOG("Cloning $to_clone...");
+			my $res = Git::command_oneline([ 'clone', $r->{origin}{fetch} ]);
+		}
+		LOG("Entering $to_clone...");
+		my $repo = Git->repository(Directory => $to_clone);
+		# Figure out what the remotes look like
+		my $res = $repo->command(qw{remote -v});
+		my %remotes = _parse_remotes($res);
+
+		# Make sure all the remotes are setup correctly.
+		foreach my $rname (keys(%$r)) {
+			my $remote = $r->{$rname};
+
+			LOG("Setting up remote $rname...");
+			$repo->command(qw{remote rm}, $rname);
+			$repo->command(qw{remote add}, $rname, $remote->{fetch});
+			$repo->command(qw{fetch}, $rname);
+			foreach my $push_uri (@{$remote->{push}}) {
+				next if $push_uri eq $remote->{fetch};
+				$res = $repo->command(qw{remote set-url --add --push}, $rname, $push_uri);
+			}
+
+		}
+
+		# TODO figure out which mirrors are missing, and add them if needed (consider privacy)
+
+		# Finally, sync up the mirrors if instructed.  This is important, as push URIs which aren't in sync will leave git in an inconsistent state.
+	}
+
 }
 
 sub _fetch_upstream_uri {