Files
.com/github-syncer-in-python.html
Kenneth Reitz 4bc7de9da5 content update
2011-01-03 01:37:40 -05:00

268 lines
7.8 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<title>GitHub Syncer in Python</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="./theme/css/main.css" type="text/css" />
<link href="./feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Kenneth's log ATOM Feed" />
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<!--[if lte IE 7]>
<link rel="stylesheet" type="text/css" media="all" href="./css/ie.css"/>
<script src="./js/IE8.js" type="text/javascript"></script><![endif]-->
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" media="all" href="./css/ie6.css"/><![endif]-->
</head>
<body id="index" class="home">
<a href="http://github.com/kennethreitz/">
<img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub" />
</a>
<header id="banner" class="body">
<h1>
<a href=".">Kenneth's log </a>
</h1>
<nav><ul>
<li >
<a href="./category/Life.html">Life</a>
</li>
<li >
<a href="./category/Code.html">Code</a>
</li>
<li class="active">
<a href="./category/projects.html">projects</a>
</li>
</ul></nav>
</header><!-- /#banner -->
<section id="content" class="body">
<article>
<header> <h1 class="entry-title"><a href="github-syncer-in-python.html"
rel="bookmark" title="Permalink to GitHub Syncer in Python">GitHub Syncer in Python</a></h1> </header>
<p>Today I rewrote a little utility I've been using for a while to
keep all of my GitHub repos up to date and organized. It updates /
clones all private, public, and watched repositories from your
account. It also detects if your repo is a mirror or fork, and
files it accordingly. My watched list is huge, but I like to have a
local copy of my favorite libraries. You never know if the owner
will take it down, or worse, move it to another SCM! ;-) The script
depends on the <strong>GitHub2</strong> module. If you don't have it, you
can install it easily.:</p>
<pre class="literal-block">
$ pip install github2
</pre>
<p>I recommend running this from <tt class="docutils literal">~/repos/</tt>.</p>
<dl class="docutils">
<dt>::</dt>
<dd><p class="first">#!/usr/bin/env python #
-<em>- coding: utf-8 -</em>-</p>
<p>&quot;&quot;&quot;Kenneth Reitz's GitHub Syncer</p>
<p>This script uses the GitHub API to get a list of all forked, mirrored, public, and
private repos in your GitHub account. If the repo already exists locally, it will
update it via git-pull. Otherwise, it will properly clone the repo.</p>
<p>It will organize your repos into the following directory structure:</p>
<ul class="simple">
<li>repos
├── forks (public fork repos)
├── mirrors (public mirror repos)
├── private (private repos)
├── public (public repos)
├── watched (this script)
└── sync.py (this script)</li>
</ul>
<p>Requires Ask Solem's github2 (<a class="reference external" href="http://pypi.python.org/pypi/github2">http://pypi.python.org/pypi/github2</a>).</p>
<p>Inspired by Gisty (<a class="reference external" href="http://github.com/swdyh/gisty">http://github.com/swdyh/gisty</a>).
&quot;&quot;&quot;</p>
<p>import os
from commands import getoutput as cmd</p>
<p>from github2.client import Github</p>
<p># GitHub configurations
GITHUB_USER = cmd('git config github.user')
GITHUB_TOKEN = cmd('git config github.token')</p>
<p># API Object
github = Github(username=GITHUB_USER, api_token=GITHUB_TOKEN)</p>
<p># repo slots
repos = {}</p>
<p>repos['watched'] = [r for r in github.repos.watching(GITHUB_USER)]
repos['private'] = []
repos['mirrors'] = []
repos['public'] = []
repos['forks'] = []</p>
<p># Collect GitHub repos via API
for repo in github.repos.list():</p>
<blockquote>
<dl class="docutils">
<dt>if repo.private:</dt>
<dd>repos['private'].append(repo)</dd>
<dt>elif repo.fork:</dt>
<dd>repos['forks'].append(repo)</dd>
<dt>elif 'mirror' in repo.description.lower():</dt>
<dd># mirrors owned by self if mirror in description...
repos['mirrors'].append(repo)</dd>
<dt>else:</dt>
<dd>repos['public'].append(repo)</dd>
</dl>
</blockquote>
<dl class="last docutils">
<dt>for org, repos in repos.iteritems():</dt>
<dd><p class="first">for repo in repos:</p>
<blockquote class="last">
<p># create org directory (safely)
try:</p>
<div class="system-message">
<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">&lt;string&gt;</tt>, line 88)</p>
Unexpected indentation.</div>
<blockquote>
os.makedirs(org)</blockquote>
<div class="system-message">
<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">&lt;string&gt;</tt>, line 89)</p>
Block quote ends without a blank line; unexpected unindent.</div>
<dl class="docutils">
<dt>except OSError:</dt>
<dd>pass</dd>
</dl>
<p># enter org dir
os.chdir(org)</p>
<p># I own the repo
private = True if org in ('private', 'fork', 'mirror') else False</p>
<p># just <cite>git pull</cite> if it's already there
if os.path.exists(repo.name):</p>
<div class="system-message">
<p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">&lt;string&gt;</tt>, line 100)</p>
Unexpected indentation.</div>
<blockquote>
os.chdir(repo.name)
print('Updating repo: %s' % (repo.name))
os.system('git pull')
os.chdir('..')</blockquote>
<div class="system-message">
<p class="system-message-title">System Message: WARNING/2 (<tt class="docutils">&lt;string&gt;</tt>, line 104)</p>
Block quote ends without a blank line; unexpected unindent.</div>
<dl class="docutils">
<dt>else:</dt>
<dd><dl class="first last docutils">
<dt>if private:</dt>
<dd>print('Cloning private repo: %s' % (repo.name))
os.system('git clone <a class="reference external" href="mailto:git&#64;github.com">git&#64;github.com</a>:%s/%s.git' % (repo.owner, repo.name))</dd>
<dt>else:</dt>
<dd>print('Cloning repo: %s' % (repo.name))
os.system('git clone git://github.com/%s/%s.git' % (repo.owner, repo.name))</dd>
</dl>
</dd>
</dl>
<p># return to base
os.chdir('..')
print</p>
</blockquote>
</dd>
</dl>
</dd>
</dl>
<p><a class="reference external" href="http://gist.github.com/619473">Source on GitHub</a> Enjoy!</p>
</div><!-- /.entry-content -->
</article>
</section>
<section id="extras" class="body">
<div class="blogroll">
<h2>Links</h2>
<ul>
<li><a href="http://github.com/kennethreitz">GitHub Repos</a></li>
<li><a href="http://flickr.com/kennethreitz">Photography (Flickr)</a></li>
<li><a href="http://twitter.com/kennethreitz">Latest Tweets</a></li>
<li><a href="http://www.linkedin.com/in/kennethreitz">R&eacute;sum&eacute;</a></li>
<li><a href="http://pick.im/kenneth-reitz">Design Portfolio</a></li>
<li><a href="http://laterstars.com/kennethreitz">Later Stars</a></li>
</ul>
</div><!-- /.blogroll -->
<div class="social">
<ul>
<li><a href="./feeds/all.atom.xml" rel="alternate">atom feed</a></li>
<li><a href="http://facebook.com/kennethreitz">Facebook</a></li>
</ul>
</div><!-- /.social -->
</section><!-- /#extras -->
<footer id="contentinfo" class="body">
<address id="about" class="vcard body">
&copy; 2011 Kenneth Reitz &amp; co. All Rights Reserved.
</address><!-- /#about -->
</footer><!-- /#contentinfo -->
<script type="text/javascript">
var disqus_shortname = 'kennethreitz';
(function () {
var s = document.createElement('script'); s.async = true;
s.type = 'text/javascript';
s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>
<script type="text/javascript" charset="utf-8">
var disqus_developer = 1;
</script>
</body>
</html>