예제 #1
0
 def run(self):
     from cinnabar import VERSION
     from cinnabar.git import Git, GitProcess
     from distutils.version import StrictVersion
     parent_dir = os.path.dirname(os.path.dirname(__file__))
     if not os.path.exists(os.path.join(parent_dir, '.git')) or \
             check_enabled('no-version-check') or \
             not interval_expired('version-check', 86400, globl=True):
         return
     REPO = 'https://github.com/glandium/git-cinnabar'
     devnull = open(os.devnull, 'wb')
     if VERSION.endswith('a'):
         _, _, extra = StrictVersion(VERSION[:-1]).version
         ref = 'refs/heads/next' if extra == 0 else 'refs/heads/master'
         for line in Git.iter('ls-remote', REPO, ref, stderr=devnull):
             sha1, head = line.split()
             if head != ref:
                 continue
             proc = GitProcess('-C',
                               parent_dir,
                               'merge-base',
                               '--is-ancestor',
                               sha1,
                               'HEAD',
                               stdout=devnull,
                               stderr=devnull)
             if proc.wait() != 0:
                 self.message = (
                     'The `{}` branch of git-cinnabar was updated. '
                     'Please update your copy.\n'
                     'You can switch to the `release` branch if you want '
                     'to reduce these update notifications.'.format(
                         ref.partition('refs/heads/')[-1]))
                 break
     else:
         version = StrictVersion(VERSION)
         newer_version = version
         for line in Git.iter('ls-remote',
                              REPO,
                              'refs/tags/*',
                              stderr=devnull):
             sha1, tag = line.split()
             tag = tag.partition('refs/tags/')[-1]
             try:
                 v = StrictVersion(tag)
             except ValueError:
                 continue
             if v > newer_version:
                 newer_version = v
         if newer_version != version:
             self.message = ('New git-cinnabar version available: {} '
                             '(current version: {})'.format(
                                 newer_version, version))
예제 #2
0
 def run(self):
     from cinnabar import VERSION
     from cinnabar.git import Git, GitProcess
     from distutils.version import StrictVersion
     parent_dir = os.path.dirname(os.path.dirname(__file__))
     if not os.path.exists(os.path.join(parent_dir, '.git')) or \
             check_enabled('no-version-check') or \
             not interval_expired('version-check', 86400):
         return
     REPO = 'https://github.com/glandium/git-cinnabar'
     devnull = open(os.devnull, 'wb')
     if VERSION.endswith('a'):
         _, _, extra = StrictVersion(VERSION[:-1]).version
         ref = 'refs/heads/next' if extra == 0 else 'refs/heads/master'
         for line in Git.iter('ls-remote', REPO, ref, stderr=devnull):
             sha1, head = line.split()
             if head != ref:
                 continue
             proc = GitProcess(
                 '-C', parent_dir, 'merge-base', '--is-ancestor', sha1,
                 'HEAD', stdout=devnull, stderr=devnull)
             if proc.wait() != 0:
                 self.message = (
                     'The `{}` branch of git-cinnabar was updated. '
                     'Please update your copy.\n'
                     'You can switch to the `release` branch if you want '
                     'to reduce these update notifications.'
                     .format(ref.partition('refs/heads/')[-1]))
                 break
     else:
         version = StrictVersion(VERSION)
         newer_version = version
         for line in Git.iter('ls-remote', REPO, 'refs/tags/*',
                              stderr=devnull):
             sha1, tag = line.split()
             tag = tag.partition('refs/tags/')[-1]
             try:
                 v = StrictVersion(tag)
             except ValueError:
                 continue
             if v > newer_version:
                 newer_version = v
         if newer_version != version:
             self.message = (
                 'New version available: {} (current version: {})'
                 .format(newer_version, version))
예제 #3
0
def download(args):
    '''download a prebuilt helper'''

    helper = 'git-cinnabar-helper'
    system = args.system
    machine = args.machine

    if system.startswith('MSYS_NT'):
        system = 'Windows'

    if system == 'Darwin':
        system = 'macOS'
    elif system == 'Windows':
        helper += '.exe'
        if machine == 'AMD64':
            machine = 'x86_64'

    available = (
        ('Linux', 'x86_64'),
        ('macOS', 'x86_64'),
        ('Windows', 'x86_64'),
        ('Windows', 'x86'),
    )

    if args.list:
        for system, machine in available:
            print "%s/%s" % (system, machine)
        return 0

    if (system, machine) not in available:
        print >>sys.stderr, 'No download available for %s/%s' % (system,
                                                                 machine)
        return 1

    if args.dev is False and VERSION.endswith('a'):
        args.dev = ''

    script_path = os.path.dirname(os.path.abspath(sys.argv[0]))

    if args.dev is not False:
        sha1 = helper_hash()
        if sha1 is None:
            print >>sys.stderr, (
                'Cannot find the right development helper for this '
                'version of git cinnabar.')
            return 1
        url = 'https://index.taskcluster.net/v1/task/github'
        url += '.glandium.git-cinnabar.helper.'
        url += '{}.{}.{}.{}'.format(
            sha1, system.lower(), machine,
            args.dev.lower() if args.dev else '').rstrip('.')
        url += '/artifacts/public/{}'.format(helper)

    else:
        if system in ('Windows', 'macOS'):
            ext = 'zip'
        else:
            ext = 'tar.xz'
        REPO_BASE = 'https://github.com/glandium'
        url = '%s/git-cinnabar/releases/download/%s/git-cinnabar.%s.%s.%s' % (
            REPO_BASE, VERSION, system.lower(), machine.lower(), ext)

    if args.url:
        print url
        return 0

    try:
        import requests
    except ImportError:
        print >>sys.stderr, (
            'Downloading the helper requires the `requests` python module.')
        return 1

    if args.output:
        d = os.path.dirname(args.output)
    else:
        d = script_path
        if not os.access(d, os.W_OK):
            d = os.path.join(os.path.expanduser('~'), '.git-cinnabar')
            try:
                os.makedirs(d)
            except Exception:
                pass
            if not os.path.isdir(d):
                print >>sys.stderr, (
                    'Cannot write to either %s or %s.' % (d, script_path))
                return 1

    print 'Downloading from %s...' % url
    req = requests.get(url, stream=True)
    if req.status_code != 200:
        # Try again, just in case
        req = requests.get(url, stream=True)
    if req.status_code != 200:
        print >>sys.stderr, (
            'Download failed with status code %d\n' % req.status_code)
        print >>sys.stderr, 'Error body was:\n\n%s' % req.content
        return 1

    size = int(req.headers.get('Content-Length', '0'))

    def progress(iter, size=0):
        def _progress(iter, size):
            read = 0
            for chunk in iter:
                read += len(chunk)
                if size:
                    yield read * 100 / size, chunk
                else:
                    yield read, chunk

        fmt = ' {}%' if size else ' {} bytes'
        return progress_enum(fmt, _progress(iter, size))

    helper_content = progress(req.iter_content(chunk_size=4096), size)

    if args.dev is False:
        content = StringIO()
        for chunk in helper_content:
            content.write(chunk)

        content.seek(0)

        print 'Extracting %s...' % helper
        if ext == 'zip':
            zip = zipfile.ZipFile(content, 'r')
            info = zip.getinfo('git-cinnabar/%s' % helper)
            helper_content = progress(zip.open(info), info.file_size)
        elif ext == 'tar.xz':
            def tar_extract():
                proc = subprocess.Popen(
                    ['tar', '-JxO', 'git-cinnabar/%s' % helper],
                    stdin=subprocess.PIPE, stdout=subprocess.PIPE)

                def send(stdin, content):
                    stdin.write(content)
                    stdin.close()

                thread = threading.Thread(
                    target=send, args=(proc.stdin, content.getvalue()))
                thread.start()

                chunk = True
                while chunk:
                    chunk = proc.stdout.read(4096)
                    yield chunk
                proc.wait()
                thread.join()

            helper_content = progress(tar_extract())

        else:
            assert False

    fd, path = tempfile.mkstemp(prefix=helper, dir=d)

    success = False
    try:
        for chunk in helper_content:
            os.write(fd, chunk)

        success = True
    finally:
        os.close(fd)
        if success:
            mode = os.stat(path).st_mode
            if args.output:
                helper_path = args.output
            else:
                helper_path = os.path.join(d, helper)
            try:
                # on Windows it's necessary to remove the file first.
                os.remove(helper_path)
            except OSError as exc:
                if exc.errno != errno.ENOENT:
                    raise
                pass
            os.rename(path, helper_path)
            # Add executable bits wherever read bits are set
            mode = mode | ((mode & 0444) >> 2)
            os.chmod(helper_path, mode)

            if not args.no_config:
                Git.run('config', '--global', 'cinnabar.helper',
                        os.path.abspath(helper_path))
        else:
            os.unlink(path)

    return 0