~launchpad-pqm/bzr-svn/devel

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# Copyright (C) 2006-2009 Jelmer Vernooij <jelmer@samba.org>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""Subversion cache directory access."""

import os
import sys
import threading
import weakref

import bzrlib
from bzrlib import (
    osutils,
    trace,
    transport as _mod_transport,
    )
from bzrlib.config import (
    config_dir,
    ensure_config_dir_exists,
    )

from bzrlib.plugins.svn import version_info


class CacheConcurrencyError(Exception):
    """Unable to access cache while write is in progress."""


def write_cache_readme(path):
    f = open(path, 'w')
    try:
        f.write(
"""This directory contains information cached by the bzr-svn plugin.

It is used for performance reasons only and can be removed
without losing data.

See http://bazaar-vcs.org/BzrForeignBranches/Subversion for details.
""")
        if version_info[3] == 'exp':
            f.write("This is the directory used by the experimental version of bzr-svn.\n")
    finally:
        f.close()


def create_cache_dir():
    """Create the top-level bzr-svn cache directory.

    :return: Path to cache directory, as byte string.
    """
    ensure_config_dir_exists()
    if version_info[3] == 'exp':
        name = 'svn-cache-exp'
    else:
        name = 'svn-cache'
    if sys.platform in ("nt", "win32"):
        from bzrlib.win32utils import get_local_appdata_location
        s = get_local_appdata_location()
        assert s is not None
        # This can return a unicode string or a plain string in
        # user encoding
        if type(s) == str:
            s = s.decode(bzrlib.user_encoding)
        base_cache_dir = s.encode(osutils._fs_enc)
        cache_dir = os.path.join(base_cache_dir, name)
    else:
        base_cache_dir = config_dir()
        cache_dir = os.path.join(base_cache_dir, name)
        # Check and use old location if possible
        if not os.path.exists(cache_dir):
            try:
                from xdg.BaseDirectory import xdg_cache_home
            except ImportError:
                pass
            else:
                cache_dir = os.path.join(xdg_cache_home, "bazaar", "svn")
        if type(cache_dir) == unicode:
            cache_dir = cache_dir.encode(osutils._fs_enc)

    if not os.path.exists(cache_dir):
        os.makedirs(cache_dir)
        write_cache_readme(os.path.join(cache_dir, "README"))

    return cache_dir


_cachedbs = threading.local()
def cachedbs():
    """Get a cache for this thread's db connections."""
    try:
        return _cachedbs.cache
    except AttributeError:
        _cachedbs.cache = weakref.WeakValueDictionary()
        return _cachedbs.cache

class RepositoryCache(object):
    """Object that provides a cache related to a particular UUID."""

    def __init__(self, uuid):
        self.uuid = uuid

    def create_cache_dir(self):
        cache_dir = create_cache_dir()
        assert isinstance(cache_dir, str)
        dir = os.path.join(cache_dir, self.uuid)
        if not os.path.exists(dir):
            trace.note("Initialising Subversion metadata cache in %s.",
                       dir.decode(osutils._fs_enc))
            os.mkdir(dir)
        return dir

    def open_transport(self):
        return _mod_transport.get_transport_from_path(
            self.create_cache_dir().decode(osutils._fs_enc))

    def open_fileid_map(self):
        from bzrlib.plugins.svn.fileids import FileIdMapCache
        return FileIdMapCache(self.open_transport())

    def open_revid_map(self):
        raise NotImplementedError(self.open_revid_map)

    def open_logwalker(self):
        raise NotImplementedError(self.open_logwalker)

    def open_revision_cache(self):
        raise NotImplementedError(self.open_revision_cache)

    def open_parents(self):
        raise NotImplementedError(self.open_parents)

    def commit(self):
        pass

try:
    from bzrlib.plugins.svn.cache.tdbcache import TdbRepositoryCache
    cache_cls = TdbRepositoryCache
except ImportError:
    from bzrlib.plugins.svn.cache.sqlitecache import SqliteRepositoryCache
    cache_cls = SqliteRepositoryCache

def get_cache(uuid):
    try:
        return cachedbs()[uuid]
    except KeyError:
        db = cache_cls(uuid)
        cachedbs()[uuid] = db
        return db