gn clean: Don't delete and recreate the build directory.

This makes the behaviour of 'gn clean .' a little more shell-friendly.
Previously gn would delete the shell's current directory, which would
put the shell session into a confusing state where many commands
don't work without re-entering the directory.

Bug: 810548
Change-Id: I2f8849a770a394fe4c38ee771d0eb765dcbe1360
Reviewed-on: https://chromium-review.googlesource.com/954703
Commit-Queue: Peter Collingbourne <pcc@chromium.org>
Reviewed-by: Brett Wilson <brettw@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#541830}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 1252d9cdc7a734579d6a6be97314c5cc541a7ccc
diff --git a/tools/gn/command_clean.cc b/tools/gn/command_clean.cc
index f4b64af..8165aaa 100644
--- a/tools/gn/command_clean.cc
+++ b/tools/gn/command_clean.cc
@@ -2,6 +2,7 @@
 // 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_split.h"
@@ -93,24 +94,14 @@
     return 1;
   }
 
-  // Read the args.gn file, if any. Not all GN builds have one.
-  base::FilePath gn_args_file = build_dir.AppendASCII("args.gn");
-  std::string args_contents;
-  base::ReadFileToString(gn_args_file, &args_contents);
-
-  base::DeleteFile(build_dir, true);
-
-  // Put back the args.gn file (if any).
-  base::CreateDirectory(build_dir);
-  if (!args_contents.empty()) {
-    if (base::WriteFile(gn_args_file, args_contents.data(),
-                        static_cast<int>(args_contents.size())) == -1) {
-      // Print the previous contents of args.gn since otherwise it is lost for
-      // good which can be quite frustrating.
-      Err(Location(),
-          "Failed to write args.gn. Old contents was:\n\n" + args_contents)
-          .PrintToStdout();
-      return 1;
+  base::FileEnumerator traversal(
+      build_dir, false,
+      base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
+  for (base::FilePath current = traversal.Next(); !current.empty();
+       current = traversal.Next()) {
+    if (!base::FilePath::CompareEqualIgnoreCase(current.BaseName().value(),
+                                                FILE_PATH_LITERAL("args.gn"))) {
+      base::DeleteFile(current, true);
     }
   }