| Github-Import documentation | Contained in the Github-Import distribution. |
Github::Import - Import your project into http://github.com
# You can see your token at https://github.com/account
% cd some_project_in_git
% github-import --username jrockway --token decafbad --add-remote --push-mode all
You can also create a config file. Here is an example using a real man's editor:
% git config --add github.user jrockway
% git config --add github.token 91ceb00b1es
% git config --add github-import.remote origin # if you don't like "github"
% cd some_other_project_in_git
% github-import
This class/script provides a way to import a git repository into http://github.com.
The standard git configuration file is used to obtain values for the attributes listed below.
If no value is specified in the config file, the default one in the documentation will be used.
For instance to not push to github, set:
[github-import]
push: false
You can override on the command line by specifying --no-push or --push
depending on what you have in the file and what is the default.
All variables are taken from github-import except username and token
which also fall back to github.user and github.token.
If true nothing will actually be done, but the output will be printed.
This is a YAML file containing values for attributes.
Sets GIT_CONFIG_LOCAL to override the configuration file.
Will only override an existing GIT_CONFIG_LOCAL if explicitly set.
Defaults to ~/github-import
Defaults to false.
The github-import command line tool sets this attribute to enable getting
configuration data.
The username for github.com
If none is provided or in the config file uses $ENV{USER}.
The api token for github.com
The name of the remote to create if add_remote is specified.
Defaults to github.
The directory to imoport.
Defaults to the current directory.
The project name to use when creating on github.
Defaults to the basename of project.
If true a repository will be created on github.
Defaults to true. Requires username and token.
If true a remote will be added for the github repository.
Defaults to true.
If true the repository will be pushed to github.
Defaults to true.
If true --tags will be given to git push.
Defaults to true.
The refspec to push, given to git push.
Defaults to master.
If you want to push all your branches set to refs/heads/*:refs/heads/*.
One of all or mirror.
If specified, git push --all or git push --mirror is run instead of
pushing with a refspec.
Overrides refspec and tags.
Defaults to the SSH push URI for your github repository.
Import the repository by running all steps
Create the repository by submitting a form.
Add a remote entry for github to .git/config.
Run git push.
Jonathan Rockway
Yuval Kogman
MIT
Copyright 2009 Jonathan Rockway, Yuval Kogman, ALl rights reserved
| Github-Import documentation | Contained in the Github-Import distribution. |
package Github::Import; use Moose; use Moose::Util::TypeConstraints qw(enum); use MooseX::Types::Path::Class qw(Dir File); use Carp qw(croak); use namespace::clean -except => 'meta'; with qw(MooseX::Getopt::Dashes); our $VERSION = "0.07"; has use_config_file => ( traits => [qw(NoGetopt)], isa => "Bool", is => "ro", default => 0, ); has config_file => ( traits => [qw(Getopt)], isa => File, is => "ro", coerce => 1, cmd_aliases => "f", documentation => "Use an alternate config file", predicate => "has_config_file", ); sub _git_conf { my ( $self, $method, $var, $default ) = @_; return $default unless $self->use_config_file; local $ENV{GIT_CONFIG} = $self->config_file->stringify if $self->has_config_file; if ( defined( my $value = $self->git_handle->$method($var) ) ) { return $value; } else { return $default; } } sub _conf_var { my ( $self, @args ) = @_; $self->_git_conf( config => @args ); } sub _conf_bool { my ( $self, @args ) = @_; $self->_git_conf( config_bool => @args ); } has git_handle => ( traits => [qw(NoGetopt)], isa => "Git", is => "ro", lazy_build => 1, ); sub _build_git_handle { my $self = shift; require Git; Git->repository( Directory => $self->project ); } # command-line args has username => ( traits => [qw(Getopt)], is => 'ro', isa => 'Str', lazy_build => 1, cmd_aliases => "u", documentation => 'username for github.com (defaults to $ENV{USER})', ); sub _build_username { my $self = shift; $self->_conf_var( 'github-import.user' ) || $self->_conf_var( 'github.user' => $ENV{USER} ); } has token => ( traits => [qw(Getopt)], is => 'ro', isa => 'Str', lazy_build => 1, cmd_aliases => "P", documentation => "api token for github.com", ); sub _build_token { my $self = shift; $self->_conf_var('github-import.token') || $self->_conf_var('github.token') || croak "'token' is required"; } has ssl => ( traits => [qw(Getopt)], is => 'ro', isa => 'Bool', lazy_build => 1, documentation => "use https instead of http", cmd_aliases => "S", ); sub _build_ssl { shift->_conf_bool('github-import.ssl', 0) } has dry_run => ( traits => [qw(Getopt)], isa => "Bool", is => "ro", cmd_aliases => "n", documentation => "don't actually do anything", ); has 'project' => ( traits => [qw(Getopt)], is => 'ro', isa => Dir, default => ".", coerce => 1, cmd_aliases => "d", documentation => "the directory of the repository (default is pwd)", ); has project_name => ( traits => [qw(Getopt)], is => 'ro', isa => 'Str', lazy_build => 1, cmd_aliases => "N", documentation => "the name of the project to create", ); sub _build_project_name { my $self = shift; my $name = $self->project->absolute->dir_list(-1); $name = lc $name if $self->lowercase; $name =~ s{[:-]+}{-}g; return $name; } has lowercase => ( traits => [qw(Getopt)], is => 'ro', isa => 'Bool', lazy_build => 1, cmd_aliases => "l", documentation => "lowercase the project name for compatibility", ); sub _build_lowercase { shift->_conf_bool( 'github-import.lowercase' => 0 ) } has description => ( traits => [qw(Getopt)], is => 'ro', isa => 'Str', predicate => "has_description", cmd_aliases => "D", documentation => "Project description", ); has homepage => ( traits => [qw(Getopt)], is => 'ro', isa => 'Str', predicate => "has_homepage", cmd_aliases => "H", documentation => "Project homepage", ); has create => ( traits => [qw(Getopt)], is => 'ro', isa => 'Bool', lazy_build => 1, cmd_aliases => "c", documentation => "create the repo on github.com (default is true)", ); sub _build_create { shift->_conf_bool( 'github-import.create' => 1 ) } has push => ( traits => [qw(Getopt)], is => 'ro', isa => 'Bool', lazy_build => 1, cmd_aliases => "p", documentation => "run git push (default is true)", ); sub _build_push { shift->_conf_bool( 'github-import.push' => 1 ) } has add_remote => ( traits => [qw(Getopt)], is => "ro", isa => "Bool", lazy_build => 1, cmd_aliases => "a", documentation => "add a remote for github to .git/config (defaults to true)", ); sub _build_add_remote { shift->_conf_bool( 'github-import.add-remote' => 1 ) } has push_tags => ( traits => [qw(Getopt)], is => "ro", isa => "Bool", cmd_flag => "tags", lazy_build => 1, cmd_aliases => "t", documentation => "specify --tags to push (default is true)", ); sub _build_push_tags { shift->_conf_bool( 'github-import.push-tags' => 1 ) } has push_mode => ( traits => [qw(Getopt)], is => "ro", isa => enum([qw(all mirror)]), predicate => "has_push_mode", cmd_aliases => "m", documentation => "'all' or 'mirror', overrides other push options", ); has remote => ( traits => [qw(Getopt)], is => "ro", isa => "Str", lazy_build => 1, cmd_aliases => "r", documentation => "the remote to add to .git/config (default is 'github')", ); sub _build_remote { shift->_conf_var( 'github-import.remote' => "github" ) } has refspec => ( traits => [qw(Getopt)], is => "ro", isa => "Str", lazy_build => 1, cmd_aliases => "b", documentation => "the refspec to specify to push (default is 'master')", ); sub _build_refspec { shift->_conf_var( 'github-import.refspec' => "master" ) } has github_path => ( traits => [qw(NoGetopt)], isa => "Str", is => "ro", lazy_build => 1, ); sub _build_github_path { my $self = shift; return join '/', $self->username, $self->project_name; } has push_uri => ( traits => [qw(Getopt)], isa => "Str", is => "ro", lazy_build => 1, cmd_aliases => "u", documentation => "override the default github push uri", ); sub _build_push_uri { my $self = shift; return 'git@github.com:' . $self->github_path . '.git'; } has setup_rebase => ( traits => [qw(Getopt)], isa => "Bool", is => "ro", lazy_build => 1, documentation => "setup the new ref to auto-rebase when pulled", ); sub _build_setup_rebase { my $self = shift; my $config = $self->_conf_var('branch.autosetuprebase') || 'never'; return 1 if $config eq 'remote' || $config eq 'always'; return 0; } # internals has 'user_agent' => ( traits => ['NoGetopt'], is => 'ro', isa => 'LWP::UserAgent', default => sub { require LWP::UserAgent; LWP::UserAgent->new( requests_redirectable => [qw/GET POST/], ); } ); has 'logger' => ( traits => ['NoGetopt'], is => 'ro', isa => 'CodeRef', default => sub { return sub { warn "@_\n" } }, ); sub msg { my ( $self, @msg ) = @_; $self->logger->(@msg); } sub err { my ( $self, $msg ) = @_; croak $msg; } sub BUILD { my $self = shift; my $p = $self->project; confess "project '$p' does not exist" unless -d $p; } sub run { my $self = shift; if($self->create){ $self->msg('Adding project to github'); my $url = $self->do_create; $self->msg('Project added OK: '. $url); } if($self->add_remote){ $self->msg(sprintf 'Adding remote "%s" to existing working copy', $self->remote); $self->do_add_remote; $self->msg('Remote added'); }; if($self->push){ $self->msg('Pushing existing master to github'); # Even when github has created the repo we could still get # errors like this because it lags: ## Pushing existing master to github ## fatal: '/data/repositories/c/c3/30/32/avar/digest-whirlpool.git' does not appear to be a git repository ## fatal: The remote end hung up unexpectedly ## push --tags origin master: command returned error: 128 ## # So sleep for a bit before pushing to the repo sleep 3; $self->do_push; $self->update_config_for_pull; $self->msg('Pushed OK'); } }; sub do_create { my $self = shift; require URI; require HTTP::Request::Common; my $uri = URI->new('http://github.com/repositories'); $uri->scheme("https") if $self->ssl; unless ( $self->dry_run ) { my $res = $self->user_agent->request( HTTP::Request::Common::POST( $uri, [ 'commit' => 'Create repository', 'login' => $self->username, 'token' => $self->token, 'repository[name]' => $self->project_name, 'repository[public]' => 'true', $self->has_description ? ( 'repository[description]' => $self->description ) : (), $self->has_homepage ? ( 'repository[homepage]' => $self->homepage ) : (), ]), ); # XXX: not sure how to detect errors here, other than the obvious $self->err('Error creating project: ' . $res->status_line) unless $res->is_success; } return $uri->scheme . '://github.com/' . $self->github_path; }; sub run_git { my ( $self, @args ) = @_; unshift @args, "command" if @args % 2; my %args = @args; my ( $command, $print_output ) = @args{qw(command print_output)}; if ( $self->dry_run ) { $self->msg("git @$command"); } else { my $method = $print_output ? "command_noisy" : "command"; $self->git_handle->$method(@$command); } } sub do_add_remote { my $self = shift; my $remote = $self->remote; my $push = $self->push_uri; if ( defined( my $url = $self->_conf_var("remote.${remote}.url") ) ) { if ( $url ne $push ) { $self->err("remote $remote is already configured as $url"); } else { $self->msg("remote $remote already added"); } } else { $self->run_git( [qw(remote add), $remote, $push], ); $self->run_git( [qw(config github.repo), $self->project_name], ); } } sub do_push { my $self = shift; my $remote = $self->add_remote ? $self->remote : $self->push_uri; my $refspec = $self->refspec; my @args = $self->has_push_mode ? ( "--" . $self->push_mode, $self->remote ) : ( $self->push_tags ? "--tags" : (), $remote, $self->refspec ); $self->run_git( [ push => @args ], print_output => 1, ); } sub update_config_for_pull { my $self = shift; my $remote = $self->remote; $self->run_git( [ config => 'branch.master.remote', $remote ], ); $self->run_git( [ config => 'branch.master.merge', 'refs/heads/master' ], ); # if the standard option branch.autosetuprebase is set, then we do # the same thing that "git clone" and other utils do. $self->run_git( [ config => 'branch.master.rebase', 'true' ] ) if $self->setup_rebase; } 1; __END__