~gandelman-a/juju-deployer/darwin_redux

« back to all changes in this revision

Viewing changes to juju_deployer/vcs.py

  • Committer: Adam Gandelman
  • Date: 2013-07-10 00:05:11 UTC
  • Revision ID: adamg@canonical.com-20130710000511-b86ud2mlgtsscnfy
Create juju_deployer module, stuff all classes and utils there.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
 
2
import subprocess
 
3
 
 
4
 
 
5
from bzrlib.workingtree import WorkingTree
 
6
 
 
7
from juju_deployer.exception import ErrorExit
 
8
 
 
9
 
 
10
class Vcs(object):
 
11
 
 
12
    err_update = "Could not update branch %(path)s from %(branch_url)s\n\n "\
 
13
                 "%(output)s"
 
14
    err_branch = "Could not branch %(branch_url)s to %(path)s\n\n %(output)s"
 
15
    err_is_mod = "Couldn't determine if %(path)s was modified\n\n %(output)s"
 
16
    err_pull = "Could not pull branch @ %(branch_url)s to %(path)s\n\n "\
 
17
               "%(output)s"
 
18
    err_cur_rev = "Could not determine current revision %(path)s\n\n "\
 
19
                  "%(output)s"
 
20
 
 
21
    def __init__(self, path, origin, log):
 
22
        self.path = path
 
23
        self.log = log
 
24
        self.origin = origin
 
25
 
 
26
    def _call(self, args, error_msg, cwd=None, stderr=()):
 
27
        #print " ".join(args), "in", cwd or self.path
 
28
        try:
 
29
            stderr = stderr is None and stderr or subprocess.STDOUT
 
30
            output = subprocess.check_output(
 
31
                args, cwd=cwd or self.path, stderr=subprocess.STDOUT)
 
32
        except subprocess.CalledProcessError, e:
 
33
            #print "vcs err", " ".join(args), "[dir: %s]" % cwd
 
34
            self.log.error(error_msg % self.get_err_msg_ctx(e))
 
35
            raise ErrorExit()
 
36
        return output.strip()
 
37
 
 
38
    def get_err_msg_ctx(self, e):
 
39
        return {
 
40
            'path': self.path,
 
41
            'branch_url': self.origin,
 
42
            'exit_code': e.returncode,
 
43
            'output': e.output,
 
44
            'vcs': self.__class__.__name__.lower()}
 
45
 
 
46
    def get_cur_rev(self):
 
47
        raise NotImplementedError()
 
48
 
 
49
    def update(self, rev=None):
 
50
        raise NotImplementedError()
 
51
 
 
52
    def branch(self):
 
53
        raise NotImplementedError()
 
54
 
 
55
    def pull(self):
 
56
        raise NotImplementedError()
 
57
 
 
58
    def is_modified(self):
 
59
        raise NotImplementedError()
 
60
 
 
61
    # upstream missing revisions?
 
62
 
 
63
 
 
64
class Bzr(Vcs):
 
65
 
 
66
    def get_cur_rev(self):
 
67
        params = ["bzr", "revno", "--tree"]
 
68
        return self._call(params, self.err_cur_rev)
 
69
 
 
70
    def update(self, rev=None):
 
71
        params = ["bzr", "up"]
 
72
        if rev:
 
73
            params.extend(["-r", str(rev)])
 
74
        self._call(params, self.err_update)
 
75
 
 
76
    def pull(self):
 
77
        params = ["bzr", "pull", "--remember", self.origin]
 
78
        self._call(params, self.err_pull)
 
79
 
 
80
    def branch(self):
 
81
        params = ["bzr", "branch", self.origin, self.path]
 
82
        cwd = os.path.dirname(os.path.dirname(self.path))
 
83
        if not cwd:
 
84
            cwd = "."
 
85
        self._call(params, self.err_branch, cwd)
 
86
 
 
87
    def is_modified(self):
 
88
        # To replace with bzr cli, we need to be able to detect changes
 
89
        # to a wc @ a rev or @ trunk.
 
90
        tree = WorkingTree.open(self.path)
 
91
        return tree.has_changes()
 
92
 
 
93
 
 
94
class Git(Vcs):
 
95
 
 
96
    def get_cur_rev(self):
 
97
        params = ["git", "rev-parse", "HEAD"]
 
98
        return self._call(params, self.err_cur_rev)
 
99
 
 
100
    def update(self,  rev=None):
 
101
        params = ["git", "reset", "--merge"]
 
102
        if rev:
 
103
            params.append(rev)
 
104
        self._call(params, self.err_update)
 
105
 
 
106
    def pull(self):
 
107
        params = ["git", "pull", "master"]
 
108
        self._call(params, self.err_pull)
 
109
 
 
110
    def branch(self):
 
111
        params = ["git", "clone", self.branch]
 
112
        self._call(params, self.err_branch, os.path.dirname(self.path))
 
113
 
 
114
    def is_modified(self):
 
115
        params = ["git", "stat", "-s"]
 
116
        return bool(self._call(params, self.err_is_mod).strip())
 
117
 
 
118
    def get_origin(self):
 
119
        params = ["git", "config", "--get", "remote.origin.url"]
 
120
        return self._call(params, "")