<commit_before>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"

#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/drive/job_scheduler.h"
#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
#include "chrome/browser/google_apis/gdata_errorcode.h"
#include "chrome/browser/google_apis/gdata_wapi_parser.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace drive {
namespace file_system {

struct CreateDirectoryOperation::CreateDirectoryParams {
  CreateDirectoryParams(const base::FilePath& target_directory_path,
                        bool is_exclusive,
                        bool is_recursive,
                        const FileOperationCallback& callback)
      : target_directory_path(target_directory_path),
        is_exclusive(is_exclusive),
        is_recursive(is_recursive),
        callback(callback) {}
  ~CreateDirectoryParams() {}

  const base::FilePath target_directory_path;
  const bool is_exclusive;
  const bool is_recursive;
  FileOperationCallback callback;
};

// CreateDirectoryOperation::FindFirstMissingParentDirectoryResult
// implementation.
CreateDirectoryOperation::FindFirstMissingParentDirectoryResult::
FindFirstMissingParentDirectoryResult()
    : error(CreateDirectoryOperation::FIND_FIRST_FOUND_INVALID) {
}

void CreateDirectoryOperation::FindFirstMissingParentDirectoryResult::Init(
    FindFirstMissingParentDirectoryError in_error,
    base::FilePath in_first_missing_parent_path,
    const std::string& in_last_dir_resource_id) {
  error = in_error;
  first_missing_parent_path = in_first_missing_parent_path;
  last_dir_resource_id = in_last_dir_resource_id;
}

CreateDirectoryOperation::FindFirstMissingParentDirectoryResult::
~FindFirstMissingParentDirectoryResult() {
}

struct CreateDirectoryOperation::FindFirstMissingParentDirectoryParams {
  FindFirstMissingParentDirectoryParams(
      const std::vector<base::FilePath::StringType>& path_parts,
      const FindFirstMissingParentDirectoryCallback& callback)
      : path_parts(path_parts),
        index(0),
        callback(callback) {
    DCHECK(!callback.is_null());
  }
  ~FindFirstMissingParentDirectoryParams() {}

  std::vector<base::FilePath::StringType> path_parts;
  size_t index;
  base::FilePath current_path;
  std::string last_dir_resource_id;
  const FindFirstMissingParentDirectoryCallback callback;
};

CreateDirectoryOperation::CreateDirectoryOperation(
    JobScheduler* job_scheduler,
    internal::ResourceMetadata* metadata,
    OperationObserver* observer)
    : job_scheduler_(job_scheduler),
      metadata_(metadata),
      observer_(observer),
      weak_ptr_factory_(this) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

CreateDirectoryOperation::~CreateDirectoryOperation() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

void CreateDirectoryOperation::CreateDirectory(
    const base::FilePath& directory_path,
    bool is_exclusive,
    bool is_recursive,
    const FileOperationCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  scoped_ptr<CreateDirectoryParams> params(new CreateDirectoryParams(
      directory_path, is_exclusive, is_recursive, callback));

  FindFirstMissingParentDirectory(
      directory_path,
      base::Bind(
          &CreateDirectoryOperation::CreateDirectoryAfterFindFirstMissingPath,
          weak_ptr_factory_.GetWeakPtr(),
          base::Passed(&params)));
}

void CreateDirectoryOperation::CreateDirectoryAfterFindFirstMissingPath(
    scoped_ptr<CreateDirectoryParams> params,
    const FindFirstMissingParentDirectoryResult& result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!params->callback.is_null());

  switch (result.error) {
    case FIND_FIRST_FOUND_INVALID: {
      params->callback.Run(FILE_ERROR_NOT_FOUND);
      return;
    }
    case FIND_FIRST_DIRECTORY_ALREADY_PRESENT: {
      params->callback.Run(
          params->is_exclusive ? FILE_ERROR_EXISTS : FILE_ERROR_OK);
      return;
    }
    case FIND_FIRST_FOUND_MISSING: {
      // There is a missing folder to be created here, move on with the rest of
      // this function.
      break;
    }
    default: {
      NOTREACHED();
      break;
    }
  }

  // Do we have a parent directory here as well? We can't then create target
  // directory if this is not a recursive operation.
  if (params->target_directory_path != result.first_missing_parent_path &&
      !params->is_recursive) {
    params->callback.Run(FILE_ERROR_NOT_FOUND);
    return;
  }

  job_scheduler_->AddNewDirectory(
      result.last_dir_resource_id,
      result.first_missing_parent_path.BaseName().AsUTF8Unsafe(),
      base::Bind(&CreateDirectoryOperation::AddNewDirectory,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(&params),
                 result.first_missing_parent_path));
}

void CreateDirectoryOperation::AddNewDirectory(
    scoped_ptr<CreateDirectoryParams> params,
    const base::FilePath& created_directory_path,
    google_apis::GDataErrorCode status,
    scoped_ptr<google_apis::ResourceEntry> entry) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!params->callback.is_null());

  FileError error = util::GDataToFileError(status);
  if (error != FILE_ERROR_OK) {
    params->callback.Run(error);
    return;
  }

  metadata_->AddEntry(
      ConvertToResourceEntry(*entry),
      base::Bind(&CreateDirectoryOperation::ContinueCreateDirectory,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(&params),
                 created_directory_path));
}

void CreateDirectoryOperation::ContinueCreateDirectory(
    scoped_ptr<CreateDirectoryParams> params,
    const base::FilePath& created_directory_path,
    FileError error,
    const base::FilePath& moved_file_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!params->callback.is_null());

  if (error != FILE_ERROR_OK) {
    params->callback.Run(error);
    return;
  }
<commit_msg>Ignore FILE_ERROR_EXISTS on CreateDirectoryOperation.<commit_after>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"

#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/drive/job_scheduler.h"
#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
#include "chrome/browser/google_apis/gdata_errorcode.h"
#include "chrome/browser/google_apis/gdata_wapi_parser.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace drive {
namespace file_system {

struct CreateDirectoryOperation::CreateDirectoryParams {
  CreateDirectoryParams(const base::FilePath& target_directory_path,
                        bool is_exclusive,
                        bool is_recursive,
                        const FileOperationCallback& callback)
      : target_directory_path(target_directory_path),
        is_exclusive(is_exclusive),
        is_recursive(is_recursive),
        callback(callback) {}
  ~CreateDirectoryParams() {}

  const base::FilePath target_directory_path;
  const bool is_exclusive;
  const bool is_recursive;
  FileOperationCallback callback;
};

// CreateDirectoryOperation::FindFirstMissingParentDirectoryResult
// implementation.
CreateDirectoryOperation::FindFirstMissingParentDirectoryResult::
FindFirstMissingParentDirectoryResult()
    : error(CreateDirectoryOperation::FIND_FIRST_FOUND_INVALID) {
}

void CreateDirectoryOperation::FindFirstMissingParentDirectoryResult::Init(
    FindFirstMissingParentDirectoryError in_error,
    base::FilePath in_first_missing_parent_path,
    const std::string& in_last_dir_resource_id) {
  error = in_error;
  first_missing_parent_path = in_first_missing_parent_path;
  last_dir_resource_id = in_last_dir_resource_id;
}

CreateDirectoryOperation::FindFirstMissingParentDirectoryResult::
~FindFirstMissingParentDirectoryResult() {
}

struct CreateDirectoryOperation::FindFirstMissingParentDirectoryParams {
  FindFirstMissingParentDirectoryParams(
      const std::vector<base::FilePath::StringType>& path_parts,
      const FindFirstMissingParentDirectoryCallback& callback)
      : path_parts(path_parts),
        index(0),
        callback(callback) {
    DCHECK(!callback.is_null());
  }
  ~FindFirstMissingParentDirectoryParams() {}

  std::vector<base::FilePath::StringType> path_parts;
  size_t index;
  base::FilePath current_path;
  std::string last_dir_resource_id;
  const FindFirstMissingParentDirectoryCallback callback;
};

CreateDirectoryOperation::CreateDirectoryOperation(
    JobScheduler* job_scheduler,
    internal::ResourceMetadata* metadata,
    OperationObserver* observer)
    : job_scheduler_(job_scheduler),
      metadata_(metadata),
      observer_(observer),
      weak_ptr_factory_(this) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

CreateDirectoryOperation::~CreateDirectoryOperation() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

void CreateDirectoryOperation::CreateDirectory(
    const base::FilePath& directory_path,
    bool is_exclusive,
    bool is_recursive,
    const FileOperationCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!callback.is_null());

  scoped_ptr<CreateDirectoryParams> params(new CreateDirectoryParams(
      directory_path, is_exclusive, is_recursive, callback));

  FindFirstMissingParentDirectory(
      directory_path,
      base::Bind(
          &CreateDirectoryOperation::CreateDirectoryAfterFindFirstMissingPath,
          weak_ptr_factory_.GetWeakPtr(),
          base::Passed(&params)));
}

void CreateDirectoryOperation::CreateDirectoryAfterFindFirstMissingPath(
    scoped_ptr<CreateDirectoryParams> params,
    const FindFirstMissingParentDirectoryResult& result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!params->callback.is_null());

  switch (result.error) {
    case FIND_FIRST_FOUND_INVALID: {
      params->callback.Run(FILE_ERROR_NOT_FOUND);
      return;
    }
    case FIND_FIRST_DIRECTORY_ALREADY_PRESENT: {
      params->callback.Run(
          params->is_exclusive ? FILE_ERROR_EXISTS : FILE_ERROR_OK);
      return;
    }
    case FIND_FIRST_FOUND_MISSING: {
      // There is a missing folder to be created here, move on with the rest of
      // this function.
      break;
    }
    default: {
      NOTREACHED();
      break;
    }
  }

  // Do we have a parent directory here as well? We can't then create target
  // directory if this is not a recursive operation.
  if (params->target_directory_path != result.first_missing_parent_path &&
      !params->is_recursive) {
    params->callback.Run(FILE_ERROR_NOT_FOUND);
    return;
  }

  job_scheduler_->AddNewDirectory(
      result.last_dir_resource_id,
      result.first_missing_parent_path.BaseName().AsUTF8Unsafe(),
      base::Bind(&CreateDirectoryOperation::AddNewDirectory,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(&params),
                 result.first_missing_parent_path));
}

void CreateDirectoryOperation::AddNewDirectory(
    scoped_ptr<CreateDirectoryParams> params,
    const base::FilePath& created_directory_path,
    google_apis::GDataErrorCode status,
    scoped_ptr<google_apis::ResourceEntry> entry) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!params->callback.is_null());

  FileError error = util::GDataToFileError(status);
  if (error != FILE_ERROR_OK) {
    params->callback.Run(error);
    return;
  }

  metadata_->AddEntry(
      ConvertToResourceEntry(*entry),
      base::Bind(&CreateDirectoryOperation::ContinueCreateDirectory,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(&params),
                 created_directory_path));
}

void CreateDirectoryOperation::ContinueCreateDirectory(
    scoped_ptr<CreateDirectoryParams> params,
    const base::FilePath& created_directory_path,
    FileError error,
    const base::FilePath& moved_file_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!params->callback.is_null());

  // Depending on timing, a metadata may be updated by delta feed already.
  // So, FILE_ERROR_EXISTS is not an error.
  if (error == FILE_ERROR_EXISTS)
    error = FILE_ERROR_OK;

  if (error != FILE_ERROR_OK) {
    params->callback.Run(error);
    return;
  }

{'fraction_non_alphanumeric': 0.0953582625984553, 'fraction_numerical': 0.0009176416609314062, 'mean_word_length': 4.688560243584167, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4046043', 'n_tokens_mistral': 3722, 'n_tokens_neox': 3646, 'n_words': 616}