aboutsummaryrefslogtreecommitdiff
blob: 31e689cdeff5a4953960718c88199e0cc901f32d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# -*- coding: utf-8 -*-

"""
    client.py
    ~~~~~~~~~

    This module implements a interface between g-octave and the octave-forge
    Subversion repository.

    :copyright: (c) 2010 by Rafael Goncalves Martins
    :license: GPL-2, see LICENSE for more details.
"""

import os
import pysvn
import shutil
import subprocess
import sys
import urllib2

import revisions

from g_octave import config

class SvnClient:
    
    url = 'https://octave.svn.sourceforge.net/svnroot/octave/trunk/octave-forge/'
    categories = ['main', 'extra', 'language', 'nonfree']
    exclude = ['CONTENTS', 'INDEX', 'Makefile', 'base']
    
    def __init__(self, create_revisions=True, verbose=False):
        conf = config.Config()
        json_file = os.path.join(conf.db, 'revisions.json')
        self._verbose = verbose
        self._client = pysvn.Client()
        self._revisions = revisions.Revisions(json_file)
        self.packages = {}
        if create_revisions and not os.path.exists(json_file):
            self.update_revisions()
        else:
            self.packages = self._revisions.get()

    def update_revisions(self):
        updated = []
        for category in self.categories:
            self.packages[category] = self._list_packages(category)
        for category in self.packages:
            for package in self.packages[category]:
                old_revision = self._revisions.get(category, package)
                current_revision = self.packages[category][package]
                if current_revision is None or current_revision > old_revision:
                    self._revisions.set(category, package, current_revision)
                    updated.append((category, package))
        return updated

    def _list_packages(self, category):
        try:
            if self._verbose:
                print 'Listing packages from: ' + category
            pkg_list = self._client.list(
                self.url + '/' + category + '/',
                depth = pysvn.depth.immediates
            )
        except pysvn.ClientError, err:
            print >> sys.stderr, 'Error: ' + str(err)
        tmp = {}
        for props, lock in pkg_list:
            filename = props.repos_path.split('/')[-1]
            if filename not in self.exclude and filename != category:
                tmp[filename] = props.created_rev.number
        return tmp

    def create_description_tree(self, dest, categories=['main', 'extra', 'language']):
        for category in categories:
            if category not in self.categories:
                continue
            for pkg, revision in self.packages[category]:
                current_dir = os.path.join(dest, category, pkg)
                os.makedirs(current_dir)
                try:
                    if self._verbose:
                        print 'Fetching DESCRIPTION from: %s/%s' % (category, pkg)
                    fp = urllib2.urlopen(
                        self.url + '/' + category + '/' + pkg + '/DESCRIPTION'
                    )
                    with open(os.path.join(current_dir, 'DESCRIPTION'), 'w') as fp_:
                        shutil.copyfileobj(fp, fp_)
                except urllib2.URLError:
                    pass

    def checkout_package(self, category, name, dest, stable=True):
        if stable:
            # get DESCRIPTION revision
            try:
                info = self._client.info2(
                    self.url + '/' + category + '/' + name + '/DESCRIPTION'
                )
            except pysvn.ClientError, err:
                return False
            revision = info[0][1].last_changed_rev
        try:
            self._client.checkout(
                self.url + '/' + category + '/' + name + '/',
                dest,
                revision = stable and revision or \
                    pysvn.Revision(pysvn.opt_revision_kind.head)
            )
        except pysvn.ClientError, err:
            return False
        return True