Skip to content

Commit

Permalink
cd into the proper directory and execute:
Browse files Browse the repository at this point in the history
  • Loading branch information
vysakh0 committed Jul 19, 2024
1 parent 8edbc75 commit 4c6951c
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 5 deletions.
5 changes: 3 additions & 2 deletions src/drd/prompts/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ def example():
</steps>
</response>
Important guidelines:
1. No files in current directory
1. No files in current directory or if user explicitly tells you to create something in current directory:
- During project initialisation: Use `npx create-next-app@latest .` like cmds to create project in the same directory.
- In current directory, do not use 'cd' commands. All operations should be relative to the current directory.
- In such scenario no need to use 'cd' commands. All operations should be relative to the current directory.
- Use relative paths for all file operations.
2. When there are files in current directory
- You have to initialise a project, you can create a new directory `npx create-docusaurus@latest new-drd-docs`, as soon
Expand Down Expand Up @@ -118,4 +118,5 @@ def example():
- If the fix involves changes to configuration files, environment variables, or package installations, a restart is likely needed.
- If the fix is a simple code change that doesn't affect the server's core functionality or loaded modules, a restart may not be necessary.
- When in doubt, err on the side of caution and suggest a restart.
19. When you create new project or new files that are non-existent, never give UPDATE step.
"""
26 changes: 24 additions & 2 deletions src/drd/utils/step_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,14 @@ def execute_shell_command(self, command, timeout=300): # 5 minutes timeout
click.echo(
f"{Fore.YELLOW}Executing shell command: {command}{Style.RESET_ALL}")

if command.strip().startswith(('source ', '.')):
if command.strip().startswith(('cd', 'chdir')):
return self._handle_cd_command(command)
elif command.strip().startswith(('source', '.')):
return self._handle_source_command(command)
else:
return self._execute_single_command(command, timeout)

def _execute_single_command(self, command, timeout):
try:
process = subprocess.Popen(
command,
Expand All @@ -187,6 +192,7 @@ def execute_shell_command(self, command, timeout=300): # 5 minutes timeout
stderr=subprocess.PIPE,
text=True,
env=self.env,
cwd=self.current_dir
)

start_time = time.time()
Expand Down Expand Up @@ -216,7 +222,6 @@ def execute_shell_command(self, command, timeout=300): # 5 minutes timeout
print_error(error_message)
raise Exception(error_message)

# Update environment variables if the command was successful
self._update_env_from_command(command)

print_success("Command executed successfully.")
Expand Down Expand Up @@ -277,3 +282,20 @@ def _update_env_from_command(self, command):
# Handle simple assignment
key, value = command.split('=', 1)
self.env[key.strip()] = value.strip().strip('"\'')

def _handle_cd_command(self, command):
_, path = command.split(None, 1)
new_dir = os.path.abspath(os.path.join(self.current_dir, path))
if self.is_safe_path(new_dir):
os.chdir(new_dir)
self.current_dir = new_dir
print_info(f"Changed directory to: {self.current_dir}")
return f"Changed directory to: {self.current_dir}"
else:
print_error(f"Cannot change to directory: {new_dir}")
return f"Failed to change directory to: {new_dir}"

def reset_directory(self):
os.chdir(self.initial_dir)
self.current_dir = self.initial_dir
print_info(f"Reset directory to: {self.current_dir}")
75 changes: 74 additions & 1 deletion tests/cli/query/test_dynamic_command_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import unittest
from unittest.mock import patch, MagicMock, call
from unittest.mock import patch, MagicMock, call, mock_open
import xml.etree.ElementTree as ET

from drd.cli.query.dynamic_command_handler import (
Expand Down Expand Up @@ -195,3 +195,76 @@ def test_execute_commands_with_skipped_steps(self, mock_print_debug, mock_print_
call("Completed step 2/3"),
call("Completed step 3/3")
])

@patch('os.chdir')
@patch('os.path.abspath')
def test_handle_cd_command(self, mock_abspath, mock_chdir):
mock_abspath.return_value = '/fake/path/app'
result = self.executor._handle_cd_command('cd app')
self.assertEqual(result, "Changed directory to: /fake/path/app")
mock_chdir.assert_called_once_with('/fake/path/app')
self.assertEqual(self.executor.current_dir, '/fake/path/app')

@patch('subprocess.Popen')
def test_execute_single_command(self, mock_popen):
mock_process = MagicMock()
mock_process.poll.side_effect = [None, 0]
mock_process.stdout.readline.return_value = 'output line'
mock_process.communicate.return_value = ('', '')
mock_popen.return_value = mock_process

result = self.executor._execute_single_command('echo "Hello"', 300)
self.assertEqual(result, 'output line')
mock_popen.assert_called_once_with(
'echo "Hello"',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
env=self.executor.env,
cwd=self.executor.current_dir
)

@patch('click.confirm')
@patch('os.chdir')
@patch('os.path.abspath')
def test_execute_shell_command_cd(self, mock_abspath, mock_chdir, mock_confirm):
mock_confirm.return_value = True
mock_abspath.return_value = '/fake/path/app'
result = self.executor.execute_shell_command('cd app')
self.assertEqual(result, "Changed directory to: /fake/path/app")
mock_chdir.assert_called_once_with('/fake/path/app')
self.assertEqual(self.executor.current_dir, '/fake/path/app')

@patch('click.confirm')
@patch('subprocess.Popen')
def test_execute_shell_command_echo(self, mock_popen, mock_confirm):
mock_confirm.return_value = True
mock_process = MagicMock()
mock_process.poll.side_effect = [None, 0]
mock_process.stdout.readline.return_value = 'Hello, World!'
mock_process.communicate.return_value = ('', '')
mock_popen.return_value = mock_process

result = self.executor.execute_shell_command('echo "Hello, World!"')
self.assertEqual(result, 'Hello, World!')

@patch('os.path.exists')
@patch('builtins.open', new_callable=mock_open)
@patch('click.confirm')
def test_perform_file_operation_create(self, mock_confirm, mock_file, mock_exists):
mock_exists.return_value = False
mock_confirm.return_value = True
result = self.executor.perform_file_operation(
'CREATE', 'test.txt', 'content')
self.assertTrue(result)
mock_file.assert_called_with(os.path.join(
self.executor.current_dir, 'test.txt'), 'w')
mock_file().write.assert_called_with('content')

@patch('os.chdir')
def test_reset_directory(self, mock_chdir):
self.executor.current_dir = '/fake/path/app'
self.executor.reset_directory()
mock_chdir.assert_called_once_with(self.executor.initial_dir)
self.assertEqual(self.executor.current_dir, self.executor.initial_dir)

0 comments on commit 4c6951c

Please sign in to comment.