Skip to content

Instantly share code, notes, and snippets.

@krrr
Created December 9, 2015 06:08
Show Gist options
  • Save krrr/ea0864d36bf4f1e9f8ea to your computer and use it in GitHub Desktop.
Save krrr/ea0864d36bf4f1e9f8ea to your computer and use it in GitHub Desktop.
Implement app's update checking by git tagging
import re
import requests
from distutils.version import LooseVersion
# we are smart client and do not support dumb protocal
# protocol document: https://github.com/git/git/blob/master/Documentation/technical/http-protocol.txt
class GitHttpError(Exception):
pass
_ref_tag = re.compile(r'^[0-9a-f]+ refs/tags/(.+)$')
def get_git_repo_tags(url):
"""Fetch tags from git repository through HTTP(S) protocol.
:param url: something like "https://gitlab.com/test/test.git"
:return: a list of tags in C locale ordering, you may consider
using distutils.version.LooseVersion to compare"""
if url.endswith('/'):
url = url[:-1]
url += '/info/refs?service=git-upload-pack'
ref_tag = re.compile(r'^[0-9a-f]+ refs/tags/(.+)$')
r = requests.get(url, headers={'User-Agent': 'git-http-ls-remote'})
if not r.ok:
raise GitHttpError('code: %s' % r.status_code)
lines = r.text.split('\n')
assert lines.pop() == '0000'
l = lines.pop(0)
if not re.match(r'^[0-9a-f]{4}# service=git-upload-pack', l):
raise GitHttpError('invalid HTTP response: %s' % l)
# this line looks like "000000d1464... HEAD\x00multi_ack ... agent=git/2.6.1"
if '\x00' in lines[0]:
lines.pop(0)
tags = map(lambda x: x.group(1),
filter(None, (_ref_tag.search(i) for i in lines)))
return [i for i in tags if not i.endswith('^{}')]
repo_url = 'https://gitlab.com/krrr/Hazama.git'
newest_ver = max(map(LooseVersion, get_git_repo_tags(repo_url)))
print(newest_ver)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment