~ubuntuone-control-tower/ubuntuone-client/trunk

« back to all changes in this revision

Viewing changes to canonical/ubuntuone/storage/u1sync/scan.py

  • Committer: Rodney Dawes
  • Date: 2009-05-12 13:36:05 UTC
  • Revision ID: rodney.dawes@canonical.com-20090512133605-6aqs6e8xnnmp5u1p
        Import the code
        Hook up lint/trial tests in setup.py
        Use icontool now instead of including the render script
        Add missing python-gnome2-desktop to package dependencies
        Update debian/rules to fix the icon cache issue

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# canonical.ubuntuone.storage.u1sync.scan
 
2
#
 
3
# Directory scanning
 
4
#
 
5
# Author: Tim Cole <tim.cole@canonical.com>
 
6
#
 
7
# Copyright 2009 Canonical Ltd.
 
8
#
 
9
# This program is free software: you can redistribute it and/or modify it
 
10
# under the terms of the GNU General Public License version 3, as published
 
11
# by the Free Software Foundation.
 
12
#
 
13
# This program is distributed in the hope that it will be useful, but
 
14
# WITHOUT ANY WARRANTY; without even the implied warranties of
 
15
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
16
# PURPOSE.  See the GNU General Public License for more details.
 
17
#
 
18
# You should have received a copy of the GNU General Public License along
 
19
# with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
"""Code for scanning local directory state."""
 
21
 
 
22
from __future__ import with_statement
 
23
 
 
24
import os
 
25
import hashlib
 
26
import shutil
 
27
from errno import ENOTDIR, EINVAL
 
28
 
 
29
EMPTY_HASH = "sha1:%s" % hashlib.sha1().hexdigest()
 
30
 
 
31
from canonical.ubuntuone.storage.protocol.dircontent_pb2 import \
 
32
    DIRECTORY, FILE, SYMLINK
 
33
from canonical.ubuntuone.storage.u1sync.genericmerge import MergeNode 
 
34
from canonical.ubuntuone.storage.u1sync.utils import should_sync
 
35
 
 
36
def scan_directory(path, display_path="", quiet=False):
 
37
    """Scans a local directory and builds an in-memory tree from it."""
 
38
    if display_path != "" and not quiet:
 
39
        print display_path
 
40
 
 
41
    link_target = None
 
42
    child_names = None
 
43
    try:
 
44
        link_target = os.readlink(path)
 
45
    except OSError, e:
 
46
        if e.errno != EINVAL:
 
47
            raise
 
48
        try:
 
49
            child_names = os.listdir(path)
 
50
        except OSError, e:
 
51
            if e.errno != ENOTDIR:
 
52
                raise
 
53
 
 
54
    if link_target is not None:
 
55
        # symlink
 
56
        sum = hashlib.sha1()
 
57
        sum.update(link_target)
 
58
        content_hash = "sha1:%s" % sum.hexdigest()
 
59
        return MergeNode(node_type=SYMLINK, content_hash=content_hash)
 
60
    elif child_names is not None:
 
61
        # directory
 
62
        child_names = [n for n in child_names if should_sync(n.decode("utf-8"))]
 
63
        child_paths = [(os.path.join(path, child_name),
 
64
                        os.path.join(display_path, child_name)) \
 
65
                       for child_name in child_names]
 
66
        children = [scan_directory(child_path, child_display_path, quiet) \
 
67
                    for (child_path, child_display_path) in child_paths]
 
68
        unicode_child_names = [n.decode("utf-8") for n in child_names]
 
69
        children = dict(zip(unicode_child_names, children))
 
70
        return MergeNode(node_type=DIRECTORY, children=children)
 
71
    else:
 
72
        # regular file
 
73
        sum = hashlib.sha1()
 
74
 
 
75
 
 
76
        class HashStream(object):
 
77
            """Stream that computes hashes."""
 
78
            def write(self, bytes):
 
79
                """Accumulate bytes."""
 
80
                sum.update(bytes)
 
81
 
 
82
 
 
83
        with open(path, "r") as stream:
 
84
            shutil.copyfileobj(stream, HashStream())
 
85
        content_hash = "sha1:%s" % sum.hexdigest()
 
86
        return MergeNode(node_type=FILE, content_hash=content_hash)