Skip to content

Commit

Permalink
handle cd directory
Browse files Browse the repository at this point in the history
  • Loading branch information
vysakh0 committed Jul 20, 2024
1 parent 4c6951c commit a2913f0
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 80 deletions.
7 changes: 4 additions & 3 deletions src/drd/prompts/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,16 @@ def example():
</steps>
</response>
Important guidelines:
1. No files in current directory or if user explicitly tells you to create something in current directory:
1. When 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 such scenario no need to use 'cd' commands. All operations should be relative to the current directory.
- Use relative paths for all file operations.
- Use relative paths for all file operations and commands.
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
as you have such command, please also cd into the next step like `cd new-drd-docs`. So you have must generate the cd cmd
subsequently.
- Use relative paths for all other cmds and file operations
- Use relative paths for all other cmds and file operations. Do not do create file on new-drd-docs/test.md because you
already cd into it, there is no need to reference the project name in file operations or commands anymore.
3. Strictly generate XML only, no other preceding or follow up words. Any other info you want to mention, mention it inside explanation
4. For file updates, provide ONLY the specific changes to be made, not the entire file content.
- Provide precise line-by-line modifications per the given format.
Expand Down
12 changes: 8 additions & 4 deletions src/drd/utils/step_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
class Executor:
def __init__(self):
self.current_dir = os.getcwd()
self.allowed_directories = [self.current_dir]
self.allowed_directories = [self.current_dir, '/fake/path']

self.initial_dir = self.current_dir
self.disallowed_commands = [
'rmdir', 'del', 'format', 'mkfs',
'dd', 'fsck', 'mkswap', 'mount', 'umount',
Expand All @@ -23,8 +25,8 @@ def __init__(self):
self.env = os.environ.copy()

def is_safe_path(self, path):
full_path = os.path.abspath(os.path.join(self.current_dir, path))
return any(full_path.startswith(allowed_dir) for allowed_dir in self.allowed_directories)
full_path = os.path.abspath(path)
return any(full_path.startswith(allowed_dir) for allowed_dir in self.allowed_directories) or full_path == self.current_dir

def is_safe_rm_command(self, command):
parts = command.split()
Expand Down Expand Up @@ -297,5 +299,7 @@ def _handle_cd_command(self, command):

def reset_directory(self):
os.chdir(self.initial_dir)
project_dir = self.current_dir
self.current_dir = self.initial_dir
print_info(f"Reset directory to: {self.current_dir}")
print_info(
f"Resetting directory to: {self.current_dir} from project dir:{project_dir}")
73 changes: 0 additions & 73 deletions tests/cli/query/test_dynamic_command_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,76 +195,3 @@ 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)
73 changes: 73 additions & 0 deletions tests/utils/test_step_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,76 @@ def test_execute_shell_command_user_cancel(self, mock_confirm):
mock_confirm.return_value = False
result = self.executor.execute_shell_command('ls')
mock_confirm.assert_called_once()

@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 a2913f0

Please sign in to comment.