Add the --relative-to-command-file to "command source" so you can
authorJim Ingham <jingham@apple.com>
Tue, 28 Sep 2021 00:51:37 +0000 (17:51 -0700)
committerJim Ingham <jingham@apple.com>
Thu, 30 Sep 2021 02:33:41 +0000 (19:33 -0700)
have linked command files in a source tree and get to them all from
one main command file.

Differential Revision: https://reviews.llvm.org/D110601

lldb/source/Commands/CommandObjectCommands.cpp
lldb/source/Commands/Options.td
lldb/test/API/commands/command/source/TestCommandSource.py
lldb/test/API/commands/command/source/commands2.txt [new file with mode: 0644]
lldb/test/API/commands/command/source/not-relative.txt [new file with mode: 0644]
lldb/test/API/commands/command/source/subdir/subcmds.txt [new file with mode: 0644]

index 9a8b81c..6392798 100644 (file)
@@ -77,7 +77,7 @@ protected:
   public:
     CommandOptions()
         : Options(), m_stop_on_error(true), m_silent_run(false),
-          m_stop_on_continue(true) {}
+          m_stop_on_continue(true), m_cmd_relative_to_command_file(false) {}
 
     ~CommandOptions() override = default;
 
@@ -95,6 +95,10 @@ protected:
         error = m_stop_on_continue.SetValueFromString(option_arg);
         break;
 
+      case 'C':
+        m_cmd_relative_to_command_file = true;
+        break;
+
       case 's':
         error = m_silent_run.SetValueFromString(option_arg);
         break;
@@ -110,6 +114,7 @@ protected:
       m_stop_on_error.Clear();
       m_silent_run.Clear();
       m_stop_on_continue.Clear();
+      m_cmd_relative_to_command_file.Clear();
     }
 
     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -121,6 +126,7 @@ protected:
     OptionValueBoolean m_stop_on_error;
     OptionValueBoolean m_silent_run;
     OptionValueBoolean m_stop_on_continue;
+    OptionValueBoolean m_cmd_relative_to_command_file;
   };
 
   bool DoExecute(Args &command, CommandReturnObject &result) override {
@@ -131,7 +137,29 @@ protected:
       return false;
     }
 
+    FileSpec source_dir = {};
+    if (m_options.m_cmd_relative_to_command_file) {
+      source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
+      if (!source_dir) {
+        result.AppendError("command source -C can only be specified "
+                           "from a command file");
+        result.SetStatus(eReturnStatusFailed);
+        return false;
+      }
+    }
+
     FileSpec cmd_file(command[0].ref());
+    if (source_dir) {
+      // Prepend the source_dir to the cmd_file path:
+      if (!cmd_file.IsRelative()) {
+        result.AppendError("command source -C can only be used "
+                           "with a relative path.");
+        result.SetStatus(eReturnStatusFailed);
+        return false;
+      }
+      cmd_file.MakeAbsolute(source_dir);
+    }
+
     FileSystem::Instance().Resolve(cmd_file);
 
     CommandInterpreterRunOptions options;
index 83df2ac..3d69bb8 100644 (file)
@@ -536,6 +536,10 @@ let Command = "source" in {
     Desc<"If true, stop executing commands on continue.">;
   def source_silent_run : Option<"silent-run", "s">, Arg<"Boolean">,
     Desc<"If true don't echo commands while executing.">;
+  def cmd_relative_to_command_file : Option<"relative-to-command-file", "C">,
+    Desc<"Resolve non-absolute paths relative to the location of the "
+    "current command file. This argument can only be used when the command is "
+    "being sourced from a file.">;
 }
 
 let Command = "alias" in {
index 6d2717b..dc32e20 100644 (file)
@@ -21,7 +21,18 @@ class CommandSourceTestCase(TestBase):
         # Sourcing .lldb in the current working directory, which in turn imports
         # the "my" package that defines the date() function.
         self.runCmd("command source .lldb")
+        self.check_results()
+        
+    @no_debug_info_test
+    def test_command_source_relative(self):
+        """Test that lldb command "command source" works correctly with relative paths."""
 
+        # Sourcing .lldb in the current working directory, which in turn imports
+        # the "my" package that defines the date() function.
+        self.runCmd("command source commands2.txt")
+        self.check_results()
+        
+    def check_results(self, failure=False):
         # Python should evaluate "my.date()" successfully.
         command_interpreter = self.dbg.GetCommandInterpreter()
         self.assertTrue(command_interpreter, VALID_COMMAND_INTERPRETER)
@@ -29,6 +40,18 @@ class CommandSourceTestCase(TestBase):
         command_interpreter.HandleCommand("script my.date()", result)
 
         import datetime
-        self.expect(result.GetOutput(), "script my.date() runs successfully",
-                    exe=False,
-                    substrs=[str(datetime.date.today())])
+        if failure:
+            self.expect(result.GetOutput(), "script my.date() runs successfully",
+                        exe=False, error=True)
+        else: 
+            self.expect(result.GetOutput(), "script my.date() runs successfully",
+                        exe=False,
+                        substrs=[str(datetime.date.today())])
+        
+    @no_debug_info_test
+    def test_command_source_relative_error(self):
+        """Test that 'command source -C' gives an error for a relative path"""
+        source_dir = self.getSourceDir()
+        result = lldb.SBCommandReturnObject()
+        self.runCmd("command source --stop-on-error 1 not-relative.txt")
+        self.check_results(failure=True)
diff --git a/lldb/test/API/commands/command/source/commands2.txt b/lldb/test/API/commands/command/source/commands2.txt
new file mode 100644 (file)
index 0000000..f0850b5
--- /dev/null
@@ -0,0 +1 @@
+command source -C subdir/subcmds.txt
diff --git a/lldb/test/API/commands/command/source/not-relative.txt b/lldb/test/API/commands/command/source/not-relative.txt
new file mode 100644 (file)
index 0000000..ca90def
--- /dev/null
@@ -0,0 +1,2 @@
+command source -C /tmp/somefile.txt
+script import my
diff --git a/lldb/test/API/commands/command/source/subdir/subcmds.txt b/lldb/test/API/commands/command/source/subdir/subcmds.txt
new file mode 100644 (file)
index 0000000..c7e5933
--- /dev/null
@@ -0,0 +1 @@
+command source -C ../commands.txt