Repository: a2i2/surround

Issue:
`surround tutorial` doesn't work if destination directory doesn't exist
`surround tutorial <path>` doesn't work if the path doesn't exist. Not sure if this is intended behaviour, but it might be nice to follow what Git does, i.e.

* Create the directory if it doesn't exist
* Print error if the directory exists but isn't empty

My experience below:
```
 ➜  surround tutorial                                                                                                                                                                                                                                            
usage: surround tutorial [-h]  path
surround tutorial: error: the following arguments are required: path

 ➜  surround tutorial my-first-surround-app                                                                                                                                                                                                                               
usage: surround [-h] {tutorial,init} ...
surround: error: Invalid directory or can't write to my-first-surround-app

 ➜  mkdir surround-tutorial 
                                                                                                                                                                                                                                           
 ➜  surround tutorial my-first-surround-app                                                                                                                                                                                                                            
The tutorial project has been created.

Start by reading the README.md file at:
/home/rohan/Development/sandbox/my-first-surround-app/README.md
```

After doing the above, I ended up with all the files in `my-first-surround-app/tutorial`, instead of just in `my-first-surround-app` as I expected.

Discussion:

Patch:
diff --git a/surround/cli.py b/surround/cli.py
index e8922cb..f57dc50 100644
--- a/surround/cli.py
+++ b/surround/cli.py
@@ -93,6 +93,16 @@ def is_valid_dir(aparser, arg):
     else:
         return arg
 
+def allowed_to_access_dir(path):
+    try:
+        os.makedirs(path, exist_ok=True)
+    except OSError:
+        print("error: can't write to " + path)
+
+    if os.access(path, os.R_OK | os.W_OK | os.F_OK | os.X_OK):
+        return True
+    return False
+
 def is_valid_name(aparser, arg):
     if not arg.isalpha() or not arg.islower():
         aparser.error("Name %s must be lowercase letters" % arg)
@@ -229,26 +239,29 @@ def parse_tutorial_args(args):
 
 
 def parse_init_args(args):
-    if args.project_name:
-        project_name = args.project_name
-    else:
-        while True:
-            project_name = input("Name of project: ")
-            if not project_name.isalpha() or not project_name.islower():
-                print("Project name requires lowercase letters only")
-            else:
-                break
-
-    if args.description:
-        project_description = args.description
-    else:
-        project_description = input("What is the purpose of this project?: ")
+    if allowed_to_access_dir(args.path):
+        if args.project_name:
+            project_name = args.project_name
+        else:
+            while True:
+                project_name = input("Name of project: ")
+                if not project_name.isalpha() or not project_name.islower():
+                    print("error: project name requires lowercase letters only")
+                else:
+                    break
+
+        if args.description:
+            project_description = args.description
+        else:
+            project_description = input("What is the purpose of this project?: ")
 
-    new_dir = os.path.join(args.path, project_name)
-    if process(new_dir, PROJECTS["new"], project_name, project_description, "new"):
-        print("Project created at %s" % os.path.join(os.path.abspath(args.path), project_name))
+        new_dir = os.path.join(args.path, project_name)
+        if process(new_dir, PROJECTS["new"], project_name, project_description, "new"):
+            print("info: project created at %s" % os.path.join(os.path.abspath(args.path), project_name))
+        else:
+            print("error: directory %s already exists" % new_dir)
     else:
-        print("Directory %s already exists" % new_dir)
+        print("error: permission denied")
 
 def parse_tool_args(parsed_args, remote_parser, tool):
     if tool == "tutorial":
@@ -278,10 +291,10 @@ def main():
 
     tutorial_parser = sub_parser.add_parser('tutorial', help="Create the tutorial project")
     tutorial_parser.add_argument('tutorial', help="Create the Surround tutorial project", action='store_true')
-    tutorial_parser.add_argument('path', type=lambda x: is_valid_dir(parser, x), help="Path for creating the tutorial project", nargs='?', default="./")
+    tutorial_parser.add_argument('path', help="Path for creating the tutorial project", nargs='?', default="./")
 
     init_parser = sub_parser.add_parser('init', help="Initialise a new Surround project")
-    init_parser.add_argument('path', type=lambda x: is_valid_dir(parser, x), help="Path for creating a Surround project", nargs='?', default="./")
+    init_parser.add_argument('path', help="Path for creating a Surround project", nargs='?', default="./")
     init_parser.add_argument('-p', '--project-name', help="Name of the project", type=lambda x: is_valid_name(parser, x))
     init_parser.add_argument('-d', '--description', help="A description for the project")
 


Test patch:
diff --git a/surround/tests/cli/project_cli/init_test.py b/surround/tests/cli/project_cli/init_test.py
index 24d0f53..1bbce4e 100644
--- a/surround/tests/cli/project_cli/init_test.py
+++ b/surround/tests/cli/project_cli/init_test.py
@@ -9,13 +9,13 @@ class InitTest(unittest.TestCase):
 
     def test_happy_path(self):
         process = subprocess.run(['surround', 'init', './', '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Project created at " + os.getcwd() + "/temp\n")
+        self.assertEqual(process.stdout, "info: project created at " + os.getcwd() + "/temp\n")
 
         is_temp = os.path.isdir(os.path.join(os.getcwd() + "/temp"))
         self.assertEqual(is_temp, True)
 
         process = subprocess.run(['surround', 'init', './', '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Directory ./temp already exists\n")
+        self.assertEqual(process.stdout, "error: directory ./temp already exists\n")
 
     def tearDown(self):
         # Remove residual files
diff --git a/surround/tests/cli/remote_cli/add_test.py b/surround/tests/cli/remote_cli/add_test.py
index 07c9ea4..537a8d8 100644
--- a/surround/tests/cli/remote_cli/add_test.py
+++ b/surround/tests/cli/remote_cli/add_test.py
@@ -9,7 +9,7 @@ class AddTest(unittest.TestCase):
 
     def test_rejecting_path(self):
         process = subprocess.run(['surround', 'init', './', '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Project created at " + os.getcwd() + "/temp\n")
+        self.assertEqual(process.stdout, "info: project created at " + os.getcwd() + "/temp\n")
 
         is_temp = os.path.isdir(os.path.join(os.getcwd() + "/temp"))
         self.assertEqual(is_temp, True)
@@ -24,7 +24,7 @@ class AddTest(unittest.TestCase):
 
     def test_happy_path(self):
         process = subprocess.run(['surround', 'init', os.getcwd(), '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Project created at " + os.getcwd() + "/temp\n")
+        self.assertEqual(process.stdout, "info: project created at " + os.getcwd() + "/temp\n")
 
         is_temp = os.path.isdir(os.path.join(os.getcwd() + "/temp"))
         self.assertEqual(is_temp, True)
diff --git a/surround/tests/cli/remote_cli/list_test.py b/surround/tests/cli/remote_cli/list_test.py
index 71970eb..d993284 100644
--- a/surround/tests/cli/remote_cli/list_test.py
+++ b/surround/tests/cli/remote_cli/list_test.py
@@ -9,7 +9,7 @@ class ListTest(unittest.TestCase):
 
     def test_rejecting_path(self):
         process = subprocess.run(['surround', 'init', './', '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Project created at " + os.getcwd() + "/temp\n")
+        self.assertEqual(process.stdout, "info: project created at " + os.getcwd() + "/temp\n")
 
         is_temp = os.path.isdir(os.path.join(os.getcwd() + "/temp"))
         self.assertEqual(is_temp, True)
@@ -19,7 +19,7 @@ class ListTest(unittest.TestCase):
 
     def test_happy_path(self):
         process = subprocess.run(['surround', 'init', './', '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Project created at " + os.getcwd() + "/temp\n")
+        self.assertEqual(process.stdout, "info: project created at " + os.getcwd() + "/temp\n")
 
         is_temp = os.path.isdir(os.path.join(os.getcwd() + "/temp"))
         self.assertEqual(is_temp, True)
diff --git a/surround/tests/cli/remote_cli/remote_test.py b/surround/tests/cli/remote_cli/remote_test.py
index e8ed4cd..7236530 100644
--- a/surround/tests/cli/remote_cli/remote_test.py
+++ b/surround/tests/cli/remote_cli/remote_test.py
@@ -12,7 +12,7 @@ class RemoteTest(unittest.TestCase):
         self.assertEqual(process.stdout, "error: not a surround project\nerror: goto project root directory\n")
 
         process = subprocess.run(['surround', 'init', './', '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Project created at " + os.getcwd() + "/temp\n")
+        self.assertEqual(process.stdout, "info: project created at " + os.getcwd() + "/temp\n")
 
         is_temp = os.path.isdir(os.path.join(os.getcwd() + "/temp"))
         self.assertEqual(is_temp, True)
@@ -22,7 +22,7 @@ class RemoteTest(unittest.TestCase):
 
     def test_remote_add(self):
         process = subprocess.run(['surround', 'init', './', '-p', 'temp', '-d', 'temp'], encoding='utf-8', stdout=subprocess.PIPE)
-        self.assertEqual(process.stdout, "Project created at " + os.getcwd() + "/temp\n")
+        self.assertEqual(process.stdout, "info: project created at " + os.getcwd() + "/temp\n")
 
         is_temp = os.path.isdir(os.path.join(os.getcwd() + "/temp"))
         self.assertEqual(is_temp, True)