1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/drive/file_change.h"
6
7 #include <sstream>
8
9 #include "base/logging.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/chromeos/drive/drive.pb.h"
12
13 namespace drive {
14
Change(ChangeType change,FileType file_type)15 FileChange::Change::Change(ChangeType change, FileType file_type)
16 : change_(change), file_type_(file_type) {
17 }
18
DebugString() const19 std::string FileChange::Change::DebugString() const {
20 const char* change_string = NULL;
21 switch (change()) {
22 case ADD_OR_UPDATE:
23 change_string = "ADD_OR_UPDATE";
24 break;
25 case DELETE:
26 change_string = "DELETE";
27 break;
28 }
29 const char* type_string = "UNKNOWN";
30 switch (file_type()) {
31 case FileChange::FILE_TYPE_FILE:
32 type_string = "FILE";
33 break;
34 case FileChange::FILE_TYPE_DIRECTORY:
35 type_string = "DIRECTORY";
36 break;
37 case FILE_TYPE_UNKNOWN:
38 // Keeps it as "unknown".
39 break;
40 }
41 return base::StringPrintf("%s:%s", change_string, type_string);
42 }
43
ChangeList()44 FileChange::ChangeList::ChangeList() {
45 }
~ChangeList()46 FileChange::ChangeList::~ChangeList() {
47 }
48
Update(const Change & new_change)49 void FileChange::ChangeList::Update(const Change& new_change) {
50 if (list_.empty()) {
51 list_.push_back(new_change);
52 return;
53 }
54
55 Change& last = list_.back();
56 if (last.IsFile() != new_change.IsFile()) {
57 list_.push_back(new_change);
58 return;
59 }
60
61 if (last.change() == new_change.change())
62 return;
63
64 // ADD + DELETE on directory -> revert
65 if (!last.IsFile() && last.IsAddOrUpdate() && new_change.IsDelete()) {
66 list_.pop_back();
67 return;
68 }
69
70 // DELETE + ADD/UPDATE -> ADD/UPDATE
71 // ADD/UPDATE + DELETE -> DELETE
72 last = new_change;
73 }
74
PopAndGetNewList() const75 FileChange::ChangeList FileChange::ChangeList::PopAndGetNewList() const {
76 ChangeList changes;
77 changes.list_ = this->list_;
78 changes.list_.pop_front();
79 return changes;
80 }
81
DebugString() const82 std::string FileChange::ChangeList::DebugString() const {
83 std::ostringstream ss;
84 ss << "{ ";
85 for (size_t i = 0; i < list_.size(); ++i)
86 ss << list_[i].DebugString() << ", ";
87 ss << "}";
88 return ss.str();
89 }
90
FileChange()91 FileChange::FileChange() {
92 }
~FileChange()93 FileChange::~FileChange() {}
94
Update(const base::FilePath file_path,const FileChange::Change & new_change)95 void FileChange::Update(const base::FilePath file_path,
96 const FileChange::Change& new_change) {
97 map_[file_path].Update(new_change);
98 }
99
Update(const base::FilePath file_path,const FileChange::ChangeList & new_change)100 void FileChange::Update(const base::FilePath file_path,
101 const FileChange::ChangeList& new_change) {
102 for (ChangeList::List::const_iterator it = new_change.list().begin();
103 it != new_change.list().end();
104 it++) {
105 map_[file_path].Update(*it);
106 }
107 }
108
Update(const base::FilePath file_path,FileType file_type,FileChange::ChangeType change)109 void FileChange::Update(const base::FilePath file_path,
110 FileType file_type,
111 FileChange::ChangeType change) {
112 Update(file_path, FileChange::Change(change, file_type));
113 }
114
Update(const base::FilePath file_path,const ResourceEntry & entry,FileChange::ChangeType change)115 void FileChange::Update(const base::FilePath file_path,
116 const ResourceEntry& entry,
117 FileChange::ChangeType change) {
118 FileType type =
119 entry.deleted() ? FILE_TYPE_UNKNOWN : entry.file_info().is_directory()
120 ? FILE_TYPE_DIRECTORY
121 : FILE_TYPE_FILE;
122 Update(file_path, type, change);
123 }
124
Apply(const FileChange & new_changed_files)125 void FileChange::Apply(const FileChange& new_changed_files) {
126 for (Map::const_iterator it = new_changed_files.map().begin();
127 it != new_changed_files.map().end();
128 it++) {
129 Update(it->first, it->second);
130 }
131 }
132
CountDirectory(const base::FilePath & directory_path) const133 size_t FileChange::CountDirectory(const base::FilePath& directory_path) const {
134 size_t count = 0;
135 for (Map::const_iterator it = map_.begin(); it != map_.end(); it++) {
136 if (it->first.DirName() == directory_path)
137 count++;
138 }
139 return count;
140 }
141
DebugString() const142 std::string FileChange::DebugString() const {
143 std::ostringstream ss;
144 ss << "{ ";
145 for (FileChange::Map::const_iterator it = map_.begin(); it != map_.end();
146 it++) {
147 ss << it->first.value() << ": " << it->second.DebugString() << ", ";
148 }
149 ss << "}";
150 return ss.str();
151 }
152
153 } // namespace drive
154