project.py: convert projects to bricks

We are converting the project concept to the brick concept.
This CL renames project.json to config.json and change the portage
overlay's path.

BUG=brillo:394
TEST=unittests
TEST=`cros project create foo --deps` creates a brick.

CQ-DEPEND=CL:254744

Change-Id: If80c8d9ecd149cda02ed0ddf91379d7d059e6285
Reviewed-on: https://chromium-review.googlesource.com/254401
Tested-by: Bertrand Simonnet <bsimonnet@chromium.org>
Trybot-Ready: Bertrand Simonnet <bsimonnet@chromium.org>
Reviewed-by: Steve Fung <stevefung@chromium.org>
Commit-Queue: Bertrand Simonnet <bsimonnet@chromium.org>
diff --git a/lib/project.py b/lib/project.py
index 75fbe4a..61ba5d2 100644
--- a/lib/project.py
+++ b/lib/project.py
@@ -17,7 +17,7 @@
                         'thin-manifests': 'true',
                         'use-manifests': 'true'}
 
-_PROJECT_JSON = 'project.json'
+_CONFIG_JSON = 'config.json'
 
 
 class ProjectAlreadyExists(Exception):
@@ -52,9 +52,9 @@
     self.project_dir = project_dir
     self.config = None
     self.legacy = False
-    project_json = os.path.join(project_dir, _PROJECT_JSON)
+    config_json = os.path.join(project_dir, _CONFIG_JSON)
 
-    if not os.path.exists(project_json):
+    if not os.path.exists(config_json):
       if initial_config:
         self.UpdateConfig(initial_config)
       elif allow_legacy:
@@ -67,13 +67,15 @@
       if self.config is None:
         raise ProjectNotFound(self.project_dir)
     elif initial_config is None:
-      self.config = json.loads(osutils.ReadFile(project_json))
+      self.config = json.loads(osutils.ReadFile(config_json))
     else:
       raise ProjectAlreadyExists(self.project_dir)
 
   def _LayoutConfPath(self):
     """Returns the path to the layout.conf file."""
-    return os.path.join(self.project_dir, 'metadata', 'layout.conf')
+    if self.legacy:
+      return os.path.join(self.project_dir, 'metadata', 'layout.conf')
+    return os.path.join(self.project_dir, 'packages', 'metadata', 'layout.conf')
 
   def _WriteLayoutConf(self, content):
     """Writes layout.conf.
@@ -106,9 +108,12 @@
     Args:
       parents: list of overlay names
     """
-    osutils.WriteFile(
-        os.path.join(self.project_dir, 'profiles', 'base', 'parent'),
-        ''.join([p + '\n' for p in parents]), makedirs=True)
+    if self.legacy:
+      raise ProjectFeatureNotSupported()
+
+    osutils.WriteFile(os.path.join(self.project_dir, 'packages', 'profiles',
+                                   'base', 'parent'),
+                      ''.join([p + '\n' for p in parents]), makedirs=True)
 
   def UpdateConfig(self, config, regenerate=True):
     """Updates the project's configuration.
@@ -128,7 +133,7 @@
     self.config = config
     formatted_config = json.dumps(config, sort_keys=True, indent=4,
                                   separators=(',', ': '))
-    osutils.WriteFile(os.path.join(self.project_dir, _PROJECT_JSON),
+    osutils.WriteFile(os.path.join(self.project_dir, _CONFIG_JSON),
                       formatted_config, makedirs=True)
 
     if regenerate:
@@ -176,7 +181,7 @@
 
   def OverlayDir(self):
     """Returns the project's overlay directory."""
-    return self.project_dir
+    return os.path.join(self.project_dir, 'packages')
 
 
 def _FindProjectInOverlays(name, base=None):
diff --git a/lib/project_unittest.py b/lib/project_unittest.py
index f8be7eb..3561ee2 100644
--- a/lib/project_unittest.py
+++ b/lib/project_unittest.py
@@ -41,8 +41,8 @@
                'bar': 'foo'}
     self.project._WriteLayoutConf(content)
 
-    layout_conf = osutils.ReadFile(os.path.join(self.tempdir, 'metadata',
-                                                'layout.conf')).split('\n')
+    path = os.path.join(self.tempdir, 'packages', 'metadata', 'layout.conf')
+    layout_conf = osutils.ReadFile(path).split('\n')
 
     expected_lines = ['repo-name = hello',
                       'bar = foo',
@@ -57,8 +57,8 @@
                'foo:bar']
 
     self.project._WriteParents(parents)
-    parents_content = osutils.ReadFile(os.path.join(self.tempdir, 'profiles',
-                                                    'base', 'parent'))
+    path = os.path.join(self.tempdir, 'packages', 'profiles', 'base', 'parent')
+    parents_content = osutils.ReadFile(path)
 
     self.assertEqual('hello:bonjour\nfoo:bar\n', parents_content)
 
@@ -70,13 +70,14 @@
 
     self.project.UpdateConfig(sample_config)
 
-    self.assertExists(os.path.join(self.tempdir, 'profiles', 'base', 'parent'))
-    self.assertExists(os.path.join(self.tempdir, 'metadata', 'layout.conf'))
+    self.assertExists(os.path.join(self.tempdir, 'packages', 'profiles', 'base',
+                                   'parent'))
+    self.assertExists(self.project._LayoutConfPath())
 
   def testFindProjectInPath(self):
     """Test that we can infer the current project from the current directory."""
     self.CreateNewProject()
-    os.remove(os.path.join(self.tempdir, 'project.json'))
+    os.remove(os.path.join(self.tempdir, 'config.json'))
     project_dir = os.path.join(self.tempdir, 'foo', 'bar', 'project')
     content = {'name': 'hello'}
     project.Project(project_dir, initial_config={'name': 'hello'})
@@ -178,4 +179,4 @@
   def testOverlayDir(self):
     """Tests that overlay directory is returned correctly."""
     self.CreateNewProject()
-    self.assertEquals(self.project.project_dir, self.project.OverlayDir())
+    self.assertExists(os.path.join(self.project.OverlayDir(), 'profiles'))