Move InvokePython() function to its own source file.

This makes the function usable from other source files,
as used in a future CL that will add a new type of file
writer.

The new function is placed in the `internal` namespace
to be consistent with `internal::ExecProcess()` which
plays a similar role.

Change-Id: I246122d43cb9bdb88ae3392679716430f8e62f3a
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/16760
Commit-Queue: David Turner <digit@google.com>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
diff --git a/build/gen.py b/build/gen.py
index a463920..41d1571 100755
--- a/build/gen.py
+++ b/build/gen.py
@@ -687,6 +687,7 @@
         'src/gn/input_conversion.cc',
         'src/gn/input_file.cc',
         'src/gn/input_file_manager.cc',
+        'src/gn/invoke_python.cc',
         'src/gn/item.cc',
         'src/gn/json_project_writer.cc',
         'src/gn/label.cc',
diff --git a/src/gn/invoke_python.cc b/src/gn/invoke_python.cc
new file mode 100644
index 0000000..c54ad72
--- /dev/null
+++ b/src/gn/invoke_python.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2024 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 "gn/invoke_python.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/strings/string_number_conversions.h"
+#include "gn/build_settings.h"
+#include "gn/err.h"
+#include "gn/exec_process.h"
+#include "gn/filesystem_utils.h"
+
+namespace internal {
+
+bool InvokePython(const BuildSettings* build_settings,
+                  const base::FilePath& python_script_path,
+                  const std::string& python_script_extra_args,
+                  const base::FilePath& output_path,
+                  bool quiet,
+                  Err* err) {
+  const base::FilePath& python_path = build_settings->python_path();
+  base::CommandLine cmdline(python_path);
+  cmdline.AppendArg("--");
+  cmdline.AppendArgPath(python_script_path);
+  cmdline.AppendArgPath(output_path);
+  if (!python_script_extra_args.empty()) {
+    cmdline.AppendArg(python_script_extra_args);
+  }
+  base::FilePath startup_dir =
+      build_settings->GetFullPath(build_settings->build_dir());
+
+  std::string output;
+  std::string stderr_output;
+
+  int exit_code = 0;
+  if (!internal::ExecProcess(cmdline, startup_dir, &output, &stderr_output,
+                             &exit_code)) {
+    *err =
+        Err(Location(), "Could not execute python.",
+            "I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
+    return false;
+  }
+
+  if (!quiet) {
+    printf("%s", output.c_str());
+    fprintf(stderr, "%s", stderr_output.c_str());
+  }
+
+  if (exit_code != 0) {
+    *err = Err(Location(), "Python has quit with exit code " +
+                               base::IntToString(exit_code) + ".");
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace internal
diff --git a/src/gn/invoke_python.h b/src/gn/invoke_python.h
new file mode 100644
index 0000000..0c66dbb
--- /dev/null
+++ b/src/gn/invoke_python.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2024 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.
+
+#ifndef TOOLS_GN_INVOKE_PYTHON_H_
+#define TOOLS_GN_INVOKE_PYTHON_H_
+
+#include <string>
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+class BuildSettings;
+class Err;
+
+namespace internal {
+
+bool InvokePython(const BuildSettings* build_settings,
+                  const base::FilePath& python_script_path,
+                  const std::string& python_script_extra_args,
+                  const base::FilePath& output_path,
+                  bool quiet,
+                  Err* err);
+
+}  // namespace internal
+
+#endif  // TOOLS_UTILS_INVOKE_PYTHON_H_
diff --git a/src/gn/json_project_writer.cc b/src/gn/json_project_writer.cc
index 96ddacc..1ea06ff 100644
--- a/src/gn/json_project_writer.cc
+++ b/src/gn/json_project_writer.cc
@@ -13,13 +13,12 @@
 #include "base/files/file_path.h"
 #include "base/json/json_writer.h"
 #include "base/json/string_escape.h"
-#include "base/strings/string_number_conversions.h"
 #include "gn/builder.h"
 #include "gn/commands.h"
 #include "gn/deps_iterator.h"
 #include "gn/desc_builder.h"
-#include "gn/exec_process.h"
 #include "gn/filesystem_utils.h"
+#include "gn/invoke_python.h"
 #include "gn/scheduler.h"
 #include "gn/settings.h"
 #include "gn/string_output_buffer.h"
@@ -84,49 +83,6 @@
   return true;
 }
 
-bool InvokePython(const BuildSettings* build_settings,
-                  const base::FilePath& python_script_path,
-                  const std::string& python_script_extra_args,
-                  const base::FilePath& output_path,
-                  bool quiet,
-                  Err* err) {
-  const base::FilePath& python_path = build_settings->python_path();
-  base::CommandLine cmdline(python_path);
-  cmdline.AppendArg("--");
-  cmdline.AppendArgPath(python_script_path);
-  cmdline.AppendArgPath(output_path);
-  if (!python_script_extra_args.empty()) {
-    cmdline.AppendArg(python_script_extra_args);
-  }
-  base::FilePath startup_dir =
-      build_settings->GetFullPath(build_settings->build_dir());
-
-  std::string output;
-  std::string stderr_output;
-
-  int exit_code = 0;
-  if (!internal::ExecProcess(cmdline, startup_dir, &output, &stderr_output,
-                             &exit_code)) {
-    *err =
-        Err(Location(), "Could not execute python.",
-            "I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
-    return false;
-  }
-
-  if (!quiet) {
-    printf("%s", output.c_str());
-    fprintf(stderr, "%s", stderr_output.c_str());
-  }
-
-  if (exit_code != 0) {
-    *err = Err(Location(), "Python has quit with exit code " +
-                               base::IntToString(exit_code) + ".");
-    return false;
-  }
-
-  return true;
-}
-
 }  // namespace
 
 bool JSONProjectWriter::RunAndWriteFiles(
@@ -172,8 +128,9 @@
         script_file = SourceFile(exec_script);
       }
       base::FilePath script_path = build_settings->GetFullPath(script_file);
-      return InvokePython(build_settings, script_path, exec_script_extra_args,
-                          output_path, quiet, err);
+      return internal::InvokePython(build_settings, script_path,
+                                    exec_script_extra_args, output_path, quiet,
+                                    err);
     }
   }