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 13namespace drive { 14 15FileChange::Change::Change(ChangeType change, FileType file_type) 16 : change_(change), file_type_(file_type) { 17} 18 19std::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 44FileChange::ChangeList::ChangeList() { 45} 46FileChange::ChangeList::~ChangeList() { 47} 48 49void 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 75FileChange::ChangeList FileChange::ChangeList::PopAndGetNewList() const { 76 ChangeList changes; 77 changes.list_ = this->list_; 78 changes.list_.pop_front(); 79 return changes; 80} 81 82std::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 91FileChange::FileChange() { 92} 93FileChange::~FileChange() {} 94 95void FileChange::Update(const base::FilePath file_path, 96 const FileChange::Change& new_change) { 97 map_[file_path].Update(new_change); 98} 99 100void 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 109void 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 115void 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 125void 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 133size_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 142std::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