Clonamos un repositorio de GitHub
, digamos el de requests
.
%%bash
git clone git@github.com:kennethreitz/requests.git ~/code/requests
Cloning into '/home/vterron/code/requests'...
requests
puede continuar, pero nosotros nos quedamos atrás, usando una versión cada vez más anticuada. ¿Sería posible determinar de forma automática si hay nuevos commits disponibles en GitHub? Veamos:¶El último commit en nuestro repositorio actual lo podemos ver con git-describe
.
%%bash --out revision
cd ~/code/requests
git describe --long --dirty --tag --always
revision = revision.strip()
print "Revisión:", revision
Revisión: v2.4.3-32-g431282e
Ahora necesitamos ver cuál es el último commit en GitHub - utilizando la API.
Determinamos la URL desde la que el repositorio de clonó:
%%bash --out origen
cd ~/code/requests
git config --get remote.origin.url
print "Origen:", origen
Origen: git@github.com:kennethreitz/requests.git
Para listar los commits en un repositorio tenemos que usar GET /repos/:owner/:repo/commits
Para componer la URL necesitamos, por tanto, saber tanto el usuario como el nombre del repositorio en GitHub del que se clonó nuestro repositorio en GitHub. Eso es fácil a partir de la URL que hemos calculado antes.
# Match HTTPS and Git clones from GitHub
REGEXP = "(git@|https://)github\.com(:|/)(?P<username>\w+)/(?P<repository>\w+).git"
import re
match = re.match(REGEXP, origen)
username = match.group('username')
repository = match.group('repository')
print "username:", username
print "repository:", repository
username: kennethreitz repository: requests
A partir de estos datos ya podemos componer la URL de la API:
API_URL = "https://api.github.com/repos/{0}/{1}/commits?page=1&per_page=1"
url = API_URL.format(username, repository)
print "API URL:", url
API URL: https://api.github.com/repos/kennethreitz/requests/commits?page=1&per_page=1
Usamos ahora requests
para conectarnos y decodificamos el JSON.
import requests
headers = {'User-Agent': 'vterron'}
kwargs = dict(headers=headers, timeout=10)
r = requests.get(url, **kwargs)
data = r.json()
print data
[{u'committer': {u'following_url': u'https://api.github.com/users/Lukasa/following{/other_user}', u'events_url': u'https://api.github.com/users/Lukasa/events{/privacy}', u'organizations_url': u'https://api.github.com/users/Lukasa/orgs', u'url': u'https://api.github.com/users/Lukasa', u'gists_url': u'https://api.github.com/users/Lukasa/gists{/gist_id}', u'html_url': u'https://github.com/Lukasa', u'subscriptions_url': u'https://api.github.com/users/Lukasa/subscriptions', u'avatar_url': u'https://avatars.githubusercontent.com/u/1382556?v=3', u'repos_url': u'https://api.github.com/users/Lukasa/repos', u'received_events_url': u'https://api.github.com/users/Lukasa/received_events', u'gravatar_id': u'', u'starred_url': u'https://api.github.com/users/Lukasa/starred{/owner}{/repo}', u'site_admin': False, u'login': u'Lukasa', u'type': u'User', u'id': 1382556, u'followers_url': u'https://api.github.com/users/Lukasa/followers'}, u'author': {u'following_url': u'https://api.github.com/users/Lukasa/following{/other_user}', u'events_url': u'https://api.github.com/users/Lukasa/events{/privacy}', u'organizations_url': u'https://api.github.com/users/Lukasa/orgs', u'url': u'https://api.github.com/users/Lukasa', u'gists_url': u'https://api.github.com/users/Lukasa/gists{/gist_id}', u'html_url': u'https://github.com/Lukasa', u'subscriptions_url': u'https://api.github.com/users/Lukasa/subscriptions', u'avatar_url': u'https://avatars.githubusercontent.com/u/1382556?v=3', u'repos_url': u'https://api.github.com/users/Lukasa/repos', u'received_events_url': u'https://api.github.com/users/Lukasa/received_events', u'gravatar_id': u'', u'starred_url': u'https://api.github.com/users/Lukasa/starred{/owner}{/repo}', u'site_admin': False, u'login': u'Lukasa', u'type': u'User', u'id': 1382556, u'followers_url': u'https://api.github.com/users/Lukasa/followers'}, u'url': u'https://api.github.com/repos/kennethreitz/requests/commits/3c850b33397b2bdacec3c2c518bc08299e8b8482', u'comments_url': u'https://api.github.com/repos/kennethreitz/requests/commits/3c850b33397b2bdacec3c2c518bc08299e8b8482/comments', u'html_url': u'https://github.com/kennethreitz/requests/commit/3c850b33397b2bdacec3c2c518bc08299e8b8482', u'sha': u'3c850b33397b2bdacec3c2c518bc08299e8b8482', u'parents': [{u'url': u'https://api.github.com/repos/kennethreitz/requests/commits/ab1f493c8b6f82cbf80f8554b5fbbd02f2b2a363', u'sha': u'ab1f493c8b6f82cbf80f8554b5fbbd02f2b2a363', u'html_url': u'https://github.com/kennethreitz/requests/commit/ab1f493c8b6f82cbf80f8554b5fbbd02f2b2a363'}, {u'url': u'https://api.github.com/repos/kennethreitz/requests/commits/d249c0a9c6dccf2bd63c3d1aad365f37cc4591a1', u'sha': u'd249c0a9c6dccf2bd63c3d1aad365f37cc4591a1', u'html_url': u'https://github.com/kennethreitz/requests/commit/d249c0a9c6dccf2bd63c3d1aad365f37cc4591a1'}], u'commit': {u'committer': {u'date': u'2015-05-21T08:16:24Z', u'name': u'Cory Benfield', u'email': u'lukasaoz@gmail.com'}, u'author': {u'date': u'2015-05-21T08:16:24Z', u'name': u'Cory Benfield', u'email': u'lukasaoz@gmail.com'}, u'url': u'https://api.github.com/repos/kennethreitz/requests/git/commits/3c850b33397b2bdacec3c2c518bc08299e8b8482', u'tree': {u'url': u'https://api.github.com/repos/kennethreitz/requests/git/trees/72f2221bc36685bda116cf1fc00b9bcc103eb923', u'sha': u'72f2221bc36685bda116cf1fc00b9bcc103eb923'}, u'comment_count': 0, u'message': u'Merge pull request #2608 from radarhere/patch-1\n\nFixed typos'}}]
El último commit es el primero de todos.
last_commit = data[0]
hash_ = last_commit['sha']
date_str = last_commit['commit']['author']['date']
print "SHA1:", hash_
print "Fecha:", date_str
SHA1: 3c850b33397b2bdacec3c2c518bc08299e8b8482 Fecha: 2015-05-21T08:16:24Z
Podemos obtener el hash corto con git-rev-parse
:
%%bash -s "$hash_" --out github_hash
cd ~/code/requests
git rev-parse --short $1
github_hash = github_hash.strip()
print "SHA1 GitHub:", github_hash
SHA1 GitHub: 3c850b3
La fecha está en formato ISO 8601, YYYY-MM-DDTHH:MM:SSZ (UTC). Lo convertimos a tiempo Unix para poder trabajar fácilmente.
import time
import calendar
fmt = "%Y-%m-%dT%H:%M:%SZ"
date_struct = time.strptime(date_str, fmt)
last_github_date = calendar.timegm(date_struct)
print "Fecha (Unix):", last_github_date
Fecha (Unix): 1432196184
Si nuestro commit local es el más reciente, el hash de GitHub será una subcadena de la revisión.
print "Revisión", revision
print "SHA1 hash:", github_hash
print github_hash in revision
Revisión v2.4.3-32-g431282e SHA1 hash: 3c850b3 False
En caso de que sean diferentes, tenemos que comprobar si la fecha del commit local es más reciente que la del último commit el GitHub. Esto lo hacemos porque en caso de que nos adelantemos al repositorio, si estamos trabajando en él, no queremos mostrar ninguna advertencia.
%%bash --out last_commit_date
cd ~/code/requests
git log -1 --format='%at'
last_commit_date = last_commit_date.strip()
print "Último commit local:", last_commit_date
Último commit local: 1415391521
Para ver si nuestro último commit es más reciente:
last_commit_date > last_github_date
True