~ubuntu-branches/ubuntu/saucy/deja-dup/saucy

« back to all changes in this revision

Viewing changes to tools/duplicity/RecursiveMove.vala

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2012-06-05 13:45:39 UTC
  • mfrom: (1.1.43)
  • Revision ID: package-import@ubuntu.com-20120605134539-l35tewhkjfq4qp6e
Tags: 23.2-0ubuntu1
* New upstream release
* debian/control:
  - Add libpeas-dev to Build-Depends
  - Update valac and libglib2.0-dev versions
  - Bump debhelper version to 9
* debian/compat:
  - Bump to 9
* debian/rules:
  - Don't install new .la and .a files from upstream
* debian/patches/allow-resuming-encrypted-backup.patch:
  - Dropped, included upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
 
2
/*
 
3
    This file is part of Déjà Dup.
 
4
    For copyright information, see AUTHORS.
 
5
 
 
6
    Déjà Dup is free software: you can redistribute it and/or modify
 
7
    it under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation, either version 3 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    Déjà Dup is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
 
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with Déjà Dup.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
using GLib;
 
21
 
 
22
/**
 
23
 * Recursively moves one directory into another, merging files.  And by merge,
 
24
 * I mean it overwrites.  It skips any files it can't move and reports an
 
25
 * error, but keeps going.
 
26
 *
 
27
 * This is not optimized for remote files.  It's mostly async, but it does the
 
28
 * occasional sync operation.
 
29
 */
 
30
internal class RecursiveMove : RecursiveOp
 
31
{
 
32
  public RecursiveMove(File source, File dest)
 
33
  {
 
34
    Object(src: source, dst: dest);
 
35
  }
 
36
  
 
37
  void progress_callback(int64 current_num_bytes, int64 total_num_bytes)
 
38
  {
 
39
    // Do nothing right now
 
40
  }
 
41
  
 
42
  protected override void handle_file()
 
43
  {
 
44
    if (dst_type == FileType.DIRECTORY) {
 
45
      // GIO will throw a fit if we try to overwrite a directory with a file.
 
46
      // So cleanly delete directory first.
 
47
      
 
48
      // We don't care about doing this 100% atomically, since user is
 
49
      // intending to restore files to a previous state and implicitly doesn't
 
50
      // worry about current state as long as we restore.  It kinda sucks that
 
51
      // we'd just delete a bunch of files and possibly not restore the original
 
52
      // file, but chances are low that the following move will fail...  But
 
53
      // not guaranteed.  It'd be nice to make this more perfect.
 
54
      try {
 
55
        dst.@delete(null);
 
56
      }
 
57
      catch (Error e) {
 
58
        raise_error(src, dst, e.message);
 
59
        return;
 
60
      }
 
61
    }
 
62
    
 
63
    try {
 
64
      src.move(dst,
 
65
               FileCopyFlags.ALL_METADATA |
 
66
               FileCopyFlags.NOFOLLOW_SYMLINKS |
 
67
               FileCopyFlags.OVERWRITE,
 
68
               null,
 
69
               progress_callback);
 
70
    }
 
71
    catch (IOError.PERMISSION_DENIED e) {
 
72
      // Try just copying it (in case we didn't have write access to src's
 
73
      // parent directory).
 
74
      try {
 
75
        src.copy(dst,
 
76
                 FileCopyFlags.ALL_METADATA |
 
77
                 FileCopyFlags.NOFOLLOW_SYMLINKS |
 
78
                 FileCopyFlags.OVERWRITE,
 
79
                 null,
 
80
                 progress_callback);
 
81
      }
 
82
      catch (Error e) {
 
83
        raise_error(src, dst, e.message);
 
84
      }
 
85
    }
 
86
    catch (Error e) {
 
87
      raise_error(src, dst, e.message);
 
88
    }
 
89
  }
 
90
  
 
91
  protected override void handle_dir()
 
92
  {
 
93
    if (dst_type != FileType.UNKNOWN && dst_type != FileType.DIRECTORY) {
 
94
      // Hmmm...  Something that's not a directory is in our way.
 
95
      // Move dst file out of the way before we continue, else GIO will
 
96
      // complain.
 
97
      
 
98
      // We don't care about doing this 100% atomically, since user is
 
99
      // intending to restore files to a previous state and implicitly doesn't
 
100
      // worry about current state as long as we restore.  If we can delete
 
101
      // it, we can create a directory in its place (i.e. restore of this
 
102
      // directory is not likely to fail in a few seconds), so let's just blow
 
103
      // it away.
 
104
      try {
 
105
        dst.@delete(null);
 
106
      }
 
107
      catch (Error e) {
 
108
        raise_error(src, dst, e.message);
 
109
        return;
 
110
      }
 
111
      
 
112
      dst_type = FileType.UNKNOWN; // now the file's gone
 
113
    }
 
114
    
 
115
    if (dst_type == FileType.UNKNOWN) {
 
116
      // Create it.  The GIO move function does not guarantee that we can move
 
117
      // whole folders across filesystems.  So we'll just create it and
 
118
      // descend.  Easy enough.
 
119
      try {
 
120
        dst.make_directory(null);
 
121
      }
 
122
      catch (Error e) {
 
123
        raise_error(src, dst, e.message);
 
124
        return;
 
125
      }
 
126
    }
 
127
  }
 
128
  
 
129
  protected override void finish_dir()
 
130
  {
 
131
    // Now, we'll try to change it's settings to match our restore copy.
 
132
    // If we tried to do this first, we may remove write access before trying
 
133
    // to copy subfiles.
 
134
    try {
 
135
      src.copy_attributes(dst,
 
136
                          FileCopyFlags.NOFOLLOW_SYMLINKS |
 
137
                          FileCopyFlags.ALL_METADATA,
 
138
                          null);
 
139
    }
 
140
    catch (Error e) {
 
141
      // If we fail, no big deal.  There'll often be stuff like /home that we
 
142
      // can't change and don't care about changing.
 
143
    }
 
144
 
 
145
    try {
 
146
      src.@delete(null); // will only be deleted if empty, so we won't
 
147
                         // accidentally toss files left over from a failed
 
148
                         // restore
 
149
    }
 
150
    catch (Error e) {
 
151
      // Ignore.  It's in /tmp, so it'll disappear, and most likely is just
 
152
      // a non-empty directory.
 
153
    }
 
154
  }
 
155
  
 
156
  protected override RecursiveOp clone_for_info(FileInfo info)
 
157
  {
 
158
    var child_name = info.get_name();
 
159
    var src_child = src.get_child(child_name);
 
160
    var dst_child = dst.get_child(child_name);
 
161
    return new RecursiveMove(src_child, dst_child);
 
162
  }
 
163
}
 
164