• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 "base/files/file_enumerator.h"
6 #include "base/files/file_path.h"
7 #include "base/files/file_util.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "gn/commands.h"
11 #include "gn/err.h"
12 #include "gn/filesystem_utils.h"
13 #include "gn/ninja_build_writer.h"
14 #include "gn/setup.h"
15 
16 namespace {
17 
CleanOneDir(const std::string & dir)18 bool CleanOneDir(const std::string& dir) {
19   // Deliberately leaked to avoid expensive process teardown.
20   Setup* setup = new Setup;
21   if (!setup->DoSetup(dir, false))
22     return false;
23 
24   base::FilePath build_dir(setup->build_settings().GetFullPath(
25       SourceDir(setup->build_settings().build_dir().value())));
26 
27   // NOTE: Not all GN builds have args.gn file hence we also check here
28   // if a build.ninja.d files exists instead.
29   base::FilePath args_gn_file = build_dir.AppendASCII("args.gn");
30   base::FilePath build_ninja_d_file = build_dir.AppendASCII("build.ninja.d");
31   if (!base::PathExists(args_gn_file) &&
32       !base::PathExists(build_ninja_d_file)) {
33     Err(Location(),
34         base::StringPrintf(
35             "%s does not look like a build directory.\n",
36             FilePathToUTF8(build_ninja_d_file.DirName().value()).c_str()))
37         .PrintToStdout();
38     return false;
39   }
40 
41   // Replace existing build.ninja with just enough for ninja to call GN and
42   // regenerate ninja files.
43   if (!commands::PrepareForRegeneration(&setup->build_settings())) {
44     return false;
45   }
46 
47   // Erase everything but (user-created) args.gn and the build.ninja files we
48   // just wrote.
49   const base::FilePath::CharType* remaining[]{
50       FILE_PATH_LITERAL("args.gn"),
51       FILE_PATH_LITERAL("build.ninja"),
52       FILE_PATH_LITERAL("build.ninja.d"),
53   };
54   base::FileEnumerator traversal(
55       build_dir, false,
56       base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
57   for (base::FilePath current = traversal.Next(); !current.empty();
58        current = traversal.Next()) {
59     base::FilePath::StringType basename =
60         base::ToLowerASCII(current.BaseName().value());
61     if (std::none_of(std::begin(remaining), std::end(remaining),
62                      [&](auto rem) { return basename == rem; })) {
63       base::DeleteFile(current, true);
64     }
65   }
66 
67   return true;
68 }
69 
70 }  // namespace
71 
72 namespace commands {
73 
74 const char kClean[] = "clean";
75 const char kClean_HelpShort[] = "clean: Cleans the output directory.";
76 const char kClean_Help[] =
77     "gn clean <out_dir>...\n"
78     "\n"
79     "  Deletes the contents of the output directory except for args.gn and\n"
80     "  creates a Ninja build environment sufficient to regenerate the build.\n";
81 
RunClean(const std::vector<std::string> & args)82 int RunClean(const std::vector<std::string>& args) {
83   if (args.empty()) {
84     Err(Location(), "Missing argument.", "Usage: \"gn clean <out_dir>...\"")
85         .PrintToStdout();
86     return 1;
87   }
88 
89   for (const auto& dir : args) {
90     if (!CleanOneDir(dir))
91       return 1;
92   }
93 
94   return 0;
95 }
96 
97 }  // namespace commands
98