blob: 6dcc163149645e11902ea66453df8e1bedd96c8a [file] [log] [blame]
// Copyright 2015 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 "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "gn/commands.h"
#include "gn/err.h"
#include "gn/filesystem_utils.h"
#include "gn/ninja_build_writer.h"
#include "gn/setup.h"
namespace {
bool CleanOneDir(const std::string& dir) {
// Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
if (!setup->DoSetup(dir, false))
return false;
base::FilePath build_dir(setup->build_settings().GetFullPath(
// NOTE: Not all GN builds have file hence we also check here
// if a files exists instead.
base::FilePath args_gn_file = build_dir.AppendASCII("");
base::FilePath build_ninja_d_file = build_dir.AppendASCII("");
if (!base::PathExists(args_gn_file) &&
!base::PathExists(build_ninja_d_file)) {
"%s does not look like a build directory.\n",
return false;
// Replace existing with just enough for ninja to call GN and
// regenerate ninja files.
if (!commands::PrepareForRegeneration(&setup->build_settings())) {
return false;
// Erase everything but (user-created) and the files we
// just wrote.
const base::FilePath::CharType* remaining[]{
base::FileEnumerator traversal(
build_dir, false,
base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
for (base::FilePath current = traversal.Next(); !current.empty();
current = traversal.Next()) {
base::FilePath::StringType basename =
if (std::none_of(std::begin(remaining), std::end(remaining),
[&](auto rem) { return basename == rem; })) {
base::DeleteFile(current, true);
return true;
} // namespace
namespace commands {
const char kClean[] = "clean";
const char kClean_HelpShort[] = "clean: Cleans the output directory.";
const char kClean_Help[] =
"gn clean <out_dir>...\n"
" Deletes the contents of the output directory except for and\n"
" creates a Ninja build environment sufficient to regenerate the build.\n";
int RunClean(const std::vector<std::string>& args) {
if (args.empty()) {
Err(Location(), "Missing argument.", "Usage: \"gn clean <out_dir>...\"")
return 1;
for (const auto& dir : args) {
if (!CleanOneDir(dir))
return 1;
return 0;
} // namespace commands