We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
sam package of template with SAR metadata fails when using sam build
<!-- Make sure we don't have an existing Issue that reports the bug you are seeing (both open and closed). 
If you do find an existing Issue, re-open or add a comment to that Issue instead of creating a new one. -->

### Description

`sam package` fails, when trying to package artifacts built by `sam build`, if the template contains SAR metadata and references local files for `LicenseUrl` or `ReadmeUrl` which should get uploaded by `sam package`. Without using `sam build` that works properly, as the files are present in the template directory.

### Steps to reproduce

```
/tmp $ sam init
2019-01-14 13:44:20 Generating grammar tables from /usr/lib/python3.7/lib2to3/Grammar.txt
2019-01-14 13:44:20 Generating grammar tables from /usr/lib/python3.7/lib2to3/PatternGrammar.txt
[+] Initializing project structure...
[SUCCESS] - Read sam-app/README.md for further instructions on how to proceed
[*] Project initialization is now complete
/tmp $ cd sam-app/
```
* Insert minimal SAR-meta data into the template:
```
Metadata:
  AWS::ServerlessRepo::Application:
    Name: hello-world             
    Description: hello world
    Author: John
    SpdxLicenseId: MIT   
    LicenseUrl: ./LICENSE 
    SemanticVersion: 0.0.1
```
```
/tmp/sam-app $ echo "dummy license text" > LICENSE
/tmp/sam-app $ sam build --use-container
2019-01-14 13:45:23 Starting Build inside a container
2019-01-14 13:45:23 Found credentials in shared credentials file: ~/.aws/credentials
2019-01-14 13:45:23 Building resource 'HelloWorldFunction'

Fetching lambci/lambda:build-nodejs8.10 Docker container image......
2019-01-14 13:45:32 Mounting /tmp/sam-app/hello-world as /tmp/samcli/source:ro inside runtime container

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Package: sam package --s3-bucket <yourbucket>
    
'nodejs' runtime has not been validated!
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
/tmp/sam-app $ sam package --s3-bucket dummy

Unable to upload artifact ./LICENSE referenced by LicenseUrl parameter of AWS::ServerlessRepo::Application resource.
Parameter LicenseUrl of resource AWS::ServerlessRepo::Application refers to a file or folder that does not exist /tmp/sam-app/.aws-sam/build/LICENSE
```
### Observed result

`sam package` fails, because the `LICENSE` file isn't present in the build directory.

### Expected result

`sam package` succeeds.

### Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

1. OS: Debian/unstable
2. `sam --version`: `SAM CLI, version 0.10.0`

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `samcli/commands/_utils/template.py`
Content:
```
1 """
2 Utilities to manipulate template
3 """
4 
5 import os
6 import six
7 import yaml
8 
9 try:
10     import pathlib
11 except ImportError:
12     import pathlib2 as pathlib
13 
14 from samcli.yamlhelper import yaml_parse, yaml_dump
15 
16 
17 _RESOURCES_WITH_LOCAL_PATHS = {
18     "AWS::Serverless::Function": ["CodeUri"],
19     "AWS::Serverless::Api": ["DefinitionUri"],
20     "AWS::AppSync::GraphQLSchema": ["DefinitionS3Location"],
21     "AWS::AppSync::Resolver": ["RequestMappingTemplateS3Location", "ResponseMappingTemplateS3Location"],
22     "AWS::Lambda::Function": ["Code"],
23     "AWS::ApiGateway::RestApi": ["BodyS3Location"],
24     "AWS::ElasticBeanstalk::ApplicationVersion": ["SourceBundle"],
25     "AWS::CloudFormation::Stack": ["TemplateURL"],
26     "AWS::Serverless::Application": ["Location"],
27     "AWS::Lambda::LayerVersion": ["Content"],
28     "AWS::Serverless::LayerVersion": ["ContentUri"]
29 }
30 
31 
32 def get_template_data(template_file):
33     """
34     Read the template file, parse it as JSON/YAML and return the template as a dictionary.
35 
36     Parameters
37     ----------
38     template_file : string
39         Path to the template to read
40 
41     Returns
42     -------
43     Template data as a dictionary
44     """
45 
46     if not pathlib.Path(template_file).exists():
47         raise ValueError("Template file not found at {}".format(template_file))
48 
49     with open(template_file, 'r') as fp:
50         try:
51             return yaml_parse(fp.read())
52         except (ValueError, yaml.YAMLError) as ex:
53             raise ValueError("Failed to parse template: {}".format(str(ex)))
54 
55 
56 def move_template(src_template_path,
57                   dest_template_path,
58                   template_dict):
59     """
60     Move the SAM/CloudFormation template from ``src_template_path`` to ``dest_template_path``. For convenience, this
61     method accepts a dictionary of template data ``template_dict`` that will be written to the destination instead of
62     reading from the source file.
63 
64     SAM/CloudFormation template can contain certain properties whose value is a relative path to a local file/folder.
65     This path is always relative to the template's location. Before writing the template to ``dest_template_path`,
66     we will update these paths to be relative to the new location.
67 
68     This methods updates resource properties supported by ``aws cloudformation package`` command:
69     https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html
70 
71     You must use this method if you are reading a template from one location, modifying it, and writing it back to a
72     different location.
73 
74     Parameters
75     ----------
76     src_template_path : str
77         Path to the original location of the template
78 
79     dest_template_path : str
80         Path to the destination location where updated template should be written to
81 
82     template_dict : dict
83         Dictionary containing template contents. This dictionary will be updated & written to ``dest`` location.
84     """
85 
86     original_root = os.path.dirname(src_template_path)
87     new_root = os.path.dirname(dest_template_path)
88 
89     # Next up, we will be writing the template to a different location. Before doing so, we should
90     # update any relative paths in the template to be relative to the new location.
91     modified_template = _update_relative_paths(template_dict,
92                                                original_root,
93                                                new_root)
94 
95     with open(dest_template_path, "w") as fp:
96         fp.write(yaml_dump(modified_template))
97 
98 
99 def _update_relative_paths(template_dict,
100                            original_root,
101                            new_root):
102     """
103     SAM/CloudFormation template can contain certain properties whose value is a relative path to a local file/folder.
104     This path is usually relative to the template's location. If the template is being moved from original location
105     ``original_root`` to new location ``new_root``, use this method to update these paths to be
106     relative to ``new_root``.
107 
108     After this method is complete, it is safe to write the template to ``new_root`` without
109     breaking any relative paths.
110 
111     This methods updates resource properties supported by ``aws cloudformation package`` command:
112     https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html
113 
114     If a property is either an absolute path or a S3 URI, this method will not update them.
115 
116 
117     Parameters
118     ----------
119     template_dict : dict
120         Dictionary containing template contents. This dictionary will be updated & written to ``dest`` location.
121 
122     original_root : str
123         Path to the directory where all paths were originally set relative to. This is usually the directory
124         containing the template originally
125 
126     new_root : str
127         Path to the new directory that all paths set relative to after this method completes.
128 
129     Returns
130     -------
131     Updated dictionary
132 
133     """
134 
135     for _, resource in template_dict.get("Resources", {}).items():
136         resource_type = resource.get("Type")
137 
138         if resource_type not in _RESOURCES_WITH_LOCAL_PATHS:
139             # Unknown resource. Skipping
140             continue
141 
142         for path_prop_name in _RESOURCES_WITH_LOCAL_PATHS[resource_type]:
143             properties = resource.get("Properties", {})
144             path = properties.get(path_prop_name)
145 
146             updated_path = _resolve_relative_to(path, original_root, new_root)
147             if not updated_path:
148                 # This path does not need to get updated
149                 continue
150 
151             properties[path_prop_name] = updated_path
152 
153     # AWS::Includes can be anywhere within the template dictionary. Hence we need to recurse through the
154     # dictionary in a separate method to find and update relative paths in there
155     template_dict = _update_aws_include_relative_path(template_dict, original_root, new_root)
156 
157     return template_dict
158 
159 
160 def _update_aws_include_relative_path(template_dict, original_root, new_root):
161     """
162     Update relative paths in "AWS::Include" directive. This directive can be present at any part of the template,
163     and not just within resources.
164     """
165 
166     for key, val in template_dict.items():
167         if key == "Fn::Transform":
168             if isinstance(val, dict) and val.get("Name") == "AWS::Include":
169                 path = val.get("Parameters", {}).get("Location", {})
170                 updated_path = _resolve_relative_to(path, original_root, new_root)
171                 if not updated_path:
172                     # This path does not need to get updated
173                     continue
174 
175                 val["Parameters"]["Location"] = updated_path
176 
177         # Recurse through all dictionary values
178         elif isinstance(val, dict):
179             _update_aws_include_relative_path(val, original_root, new_root)
180         elif isinstance(val, list):
181             for item in val:
182                 if isinstance(item, dict):
183                     _update_aws_include_relative_path(item, original_root, new_root)
184 
185     return template_dict
186 
187 
188 def _resolve_relative_to(path, original_root, new_root):
189     """
190     If the given ``path`` is a relative path, then assume it is relative to ``original_root``. This method will
191     update the path to be resolve it relative to ``new_root`` and return.
192 
193     Examples
194     -------
195         # Assume a file called template.txt at location /tmp/original/root/template.txt expressed as relative path
196         # We are trying to update it to be relative to /tmp/new/root instead of the /tmp/original/root
197         >>> result = _resolve_relative_to("template.txt",  \
198                                           "/tmp/original/root", \
199                                           "/tmp/new/root")
200         >>> result
201         ../../original/root/template.txt
202 
203     Returns
204     -------
205     Updated path if the given path is a relative path. None, if the path is not a relative path.
206     """
207 
208     if not isinstance(path, six.string_types) \
209             or path.startswith("s3://") \
210             or os.path.isabs(path):
211         # Value is definitely NOT a relative path. It is either a S3 URi or Absolute path or not a string at all
212         return None
213 
214     # Value is definitely a relative path. Change it relative to the destination directory
215     return os.path.relpath(
216         os.path.normpath(os.path.join(original_root, path)),  # Absolute original path w.r.t ``original_root``
217         new_root)  # Resolve the original path with respect to ``new_root``
218
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/samcli/commands/_utils/template.py b/samcli/commands/_utils/template.py
--- a/samcli/commands/_utils/template.py
+++ b/samcli/commands/_utils/template.py
@@ -14,6 +14,10 @@
 from samcli.yamlhelper import yaml_parse, yaml_dump
 
 
+_METADATA_WITH_LOCAL_PATHS = {
+    "AWS::ServerlessRepo::Application": ["LicenseUrl", "ReadmeUrl"]
+}
+
 _RESOURCES_WITH_LOCAL_PATHS = {
     "AWS::Serverless::Function": ["CodeUri"],
     "AWS::Serverless::Api": ["DefinitionUri"],
@@ -132,6 +136,22 @@
 
     """
 
+    for resource_type, properties in template_dict.get("Metadata", {}).items():
+
+        if resource_type not in _METADATA_WITH_LOCAL_PATHS:
+            # Unknown resource. Skipping
+            continue
+
+        for path_prop_name in _METADATA_WITH_LOCAL_PATHS[resource_type]:
+            path = properties.get(path_prop_name)
+
+            updated_path = _resolve_relative_to(path, original_root, new_root)
+            if not updated_path:
+                # This path does not need to get updated
+                continue
+
+            properties[path_prop_name] = updated_path
+
     for _, resource in template_dict.get("Resources", {}).items():
         resource_type = resource.get("Type")

{"golden_diff": "diff --git a/samcli/commands/_utils/template.py b/samcli/commands/_utils/template.py\n--- a/samcli/commands/_utils/template.py\n+++ b/samcli/commands/_utils/template.py\n@@ -14,6 +14,10 @@\n from samcli.yamlhelper import yaml_parse, yaml_dump\n \n \n+_METADATA_WITH_LOCAL_PATHS = {\n+    \"AWS::ServerlessRepo::Application\": [\"LicenseUrl\", \"ReadmeUrl\"]\n+}\n+\n _RESOURCES_WITH_LOCAL_PATHS = {\n     \"AWS::Serverless::Function\": [\"CodeUri\"],\n     \"AWS::Serverless::Api\": [\"DefinitionUri\"],\n@@ -132,6 +136,22 @@\n \n     \"\"\"\n \n+    for resource_type, properties in template_dict.get(\"Metadata\", {}).items():\n+\n+        if resource_type not in _METADATA_WITH_LOCAL_PATHS:\n+            # Unknown resource. Skipping\n+            continue\n+\n+        for path_prop_name in _METADATA_WITH_LOCAL_PATHS[resource_type]:\n+            path = properties.get(path_prop_name)\n+\n+            updated_path = _resolve_relative_to(path, original_root, new_root)\n+            if not updated_path:\n+                # This path does not need to get updated\n+                continue\n+\n+            properties[path_prop_name] = updated_path\n+\n     for _, resource in template_dict.get(\"Resources\", {}).items():\n         resource_type = resource.get(\"Type\")\n", "issue": "sam package of template with SAR metadata fails when using sam build\n<!-- Make sure we don't have an existing Issue that reports the bug you are seeing (both open and closed). \r\nIf you do find an existing Issue, re-open or add a comment to that Issue instead of creating a new one. -->\r\n\r\n### Description\r\n\r\n`sam package` fails, when trying to package artifacts built by `sam build`, if the template contains SAR metadata and references local files for `LicenseUrl` or `ReadmeUrl` which should get uploaded by `sam package`. Without using `sam build` that works properly, as the files are present in the template directory.\r\n\r\n### Steps to reproduce\r\n\r\n```\r\n/tmp $ sam init\r\n2019-01-14 13:44:20 Generating grammar tables from /usr/lib/python3.7/lib2to3/Grammar.txt\r\n2019-01-14 13:44:20 Generating grammar tables from /usr/lib/python3.7/lib2to3/PatternGrammar.txt\r\n[+] Initializing project structure...\r\n[SUCCESS] - Read sam-app/README.md for further instructions on how to proceed\r\n[*] Project initialization is now complete\r\n/tmp $ cd sam-app/\r\n```\r\n* Insert minimal SAR-meta data into the template:\r\n```\r\nMetadata:\r\n  AWS::ServerlessRepo::Application:\r\n    Name: hello-world             \r\n    Description: hello world\r\n    Author: John\r\n    SpdxLicenseId: MIT   \r\n    LicenseUrl: ./LICENSE \r\n    SemanticVersion: 0.0.1\r\n```\r\n```\r\n/tmp/sam-app $ echo \"dummy license text\" > LICENSE\r\n/tmp/sam-app $ sam build --use-container\r\n2019-01-14 13:45:23 Starting Build inside a container\r\n2019-01-14 13:45:23 Found credentials in shared credentials file: ~/.aws/credentials\r\n2019-01-14 13:45:23 Building resource 'HelloWorldFunction'\r\n\r\nFetching lambci/lambda:build-nodejs8.10 Docker container image......\r\n2019-01-14 13:45:32 Mounting /tmp/sam-app/hello-world as /tmp/samcli/source:ro inside runtime container\r\n\r\nBuild Succeeded\r\n\r\nBuilt Artifacts  : .aws-sam/build\r\nBuilt Template   : .aws-sam/build/template.yaml\r\n\r\nCommands you can use next\r\n=========================\r\n[*] Invoke Function: sam local invoke\r\n[*] Package: sam package --s3-bucket <yourbucket>\r\n    \r\n'nodejs' runtime has not been validated!\r\nRunning NodejsNpmBuilder:NpmPack\r\nRunning NodejsNpmBuilder:CopySource\r\nRunning NodejsNpmBuilder:NpmInstall\r\n/tmp/sam-app $ sam package --s3-bucket dummy\r\n\r\nUnable to upload artifact ./LICENSE referenced by LicenseUrl parameter of AWS::ServerlessRepo::Application resource.\r\nParameter LicenseUrl of resource AWS::ServerlessRepo::Application refers to a file or folder that does not exist /tmp/sam-app/.aws-sam/build/LICENSE\r\n```\r\n### Observed result\r\n\r\n`sam package` fails, because the `LICENSE` file isn't present in the build directory.\r\n\r\n### Expected result\r\n\r\n`sam package` succeeds.\r\n\r\n### Additional environment details (Ex: Windows, Mac, Amazon Linux etc)\r\n\r\n1. OS: Debian/unstable\r\n2. `sam --version`: `SAM CLI, version 0.10.0`\n", "before_files": [{"content": "\"\"\"\nUtilities to manipulate template\n\"\"\"\n\nimport os\nimport six\nimport yaml\n\ntry:\n    import pathlib\nexcept ImportError:\n    import pathlib2 as pathlib\n\nfrom samcli.yamlhelper import yaml_parse, yaml_dump\n\n\n_RESOURCES_WITH_LOCAL_PATHS = {\n    \"AWS::Serverless::Function\": [\"CodeUri\"],\n    \"AWS::Serverless::Api\": [\"DefinitionUri\"],\n    \"AWS::AppSync::GraphQLSchema\": [\"DefinitionS3Location\"],\n    \"AWS::AppSync::Resolver\": [\"RequestMappingTemplateS3Location\", \"ResponseMappingTemplateS3Location\"],\n    \"AWS::Lambda::Function\": [\"Code\"],\n    \"AWS::ApiGateway::RestApi\": [\"BodyS3Location\"],\n    \"AWS::ElasticBeanstalk::ApplicationVersion\": [\"SourceBundle\"],\n    \"AWS::CloudFormation::Stack\": [\"TemplateURL\"],\n    \"AWS::Serverless::Application\": [\"Location\"],\n    \"AWS::Lambda::LayerVersion\": [\"Content\"],\n    \"AWS::Serverless::LayerVersion\": [\"ContentUri\"]\n}\n\n\ndef get_template_data(template_file):\n    \"\"\"\n    Read the template file, parse it as JSON/YAML and return the template as a dictionary.\n\n    Parameters\n    ----------\n    template_file : string\n        Path to the template to read\n\n    Returns\n    -------\n    Template data as a dictionary\n    \"\"\"\n\n    if not pathlib.Path(template_file).exists():\n        raise ValueError(\"Template file not found at {}\".format(template_file))\n\n    with open(template_file, 'r') as fp:\n        try:\n            return yaml_parse(fp.read())\n        except (ValueError, yaml.YAMLError) as ex:\n            raise ValueError(\"Failed to parse template: {}\".format(str(ex)))\n\n\ndef move_template(src_template_path,\n                  dest_template_path,\n                  template_dict):\n    \"\"\"\n    Move the SAM/CloudFormation template from ``src_template_path`` to ``dest_template_path``. For convenience, this\n    method accepts a dictionary of template data ``template_dict`` that will be written to the destination instead of\n    reading from the source file.\n\n    SAM/CloudFormation template can contain certain properties whose value is a relative path to a local file/folder.\n    This path is always relative to the template's location. Before writing the template to ``dest_template_path`,\n    we will update these paths to be relative to the new location.\n\n    This methods updates resource properties supported by ``aws cloudformation package`` command:\n    https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html\n\n    You must use this method if you are reading a template from one location, modifying it, and writing it back to a\n    different location.\n\n    Parameters\n    ----------\n    src_template_path : str\n        Path to the original location of the template\n\n    dest_template_path : str\n        Path to the destination location where updated template should be written to\n\n    template_dict : dict\n        Dictionary containing template contents. This dictionary will be updated & written to ``dest`` location.\n    \"\"\"\n\n    original_root = os.path.dirname(src_template_path)\n    new_root = os.path.dirname(dest_template_path)\n\n    # Next up, we will be writing the template to a different location. Before doing so, we should\n    # update any relative paths in the template to be relative to the new location.\n    modified_template = _update_relative_paths(template_dict,\n                                               original_root,\n                                               new_root)\n\n    with open(dest_template_path, \"w\") as fp:\n        fp.write(yaml_dump(modified_template))\n\n\ndef _update_relative_paths(template_dict,\n                           original_root,\n                           new_root):\n    \"\"\"\n    SAM/CloudFormation template can contain certain properties whose value is a relative path to a local file/folder.\n    This path is usually relative to the template's location. If the template is being moved from original location\n    ``original_root`` to new location ``new_root``, use this method to update these paths to be\n    relative to ``new_root``.\n\n    After this method is complete, it is safe to write the template to ``new_root`` without\n    breaking any relative paths.\n\n    This methods updates resource properties supported by ``aws cloudformation package`` command:\n    https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html\n\n    If a property is either an absolute path or a S3 URI, this method will not update them.\n\n\n    Parameters\n    ----------\n    template_dict : dict\n        Dictionary containing template contents. This dictionary will be updated & written to ``dest`` location.\n\n    original_root : str\n        Path to the directory where all paths were originally set relative to. This is usually the directory\n        containing the template originally\n\n    new_root : str\n        Path to the new directory that all paths set relative to after this method completes.\n\n    Returns\n    -------\n    Updated dictionary\n\n    \"\"\"\n\n    for _, resource in template_dict.get(\"Resources\", {}).items():\n        resource_type = resource.get(\"Type\")\n\n        if resource_type not in _RESOURCES_WITH_LOCAL_PATHS:\n            # Unknown resource. Skipping\n            continue\n\n        for path_prop_name in _RESOURCES_WITH_LOCAL_PATHS[resource_type]:\n            properties = resource.get(\"Properties\", {})\n            path = properties.get(path_prop_name)\n\n            updated_path = _resolve_relative_to(path, original_root, new_root)\n            if not updated_path:\n                # This path does not need to get updated\n                continue\n\n            properties[path_prop_name] = updated_path\n\n    # AWS::Includes can be anywhere within the template dictionary. Hence we need to recurse through the\n    # dictionary in a separate method to find and update relative paths in there\n    template_dict = _update_aws_include_relative_path(template_dict, original_root, new_root)\n\n    return template_dict\n\n\ndef _update_aws_include_relative_path(template_dict, original_root, new_root):\n    \"\"\"\n    Update relative paths in \"AWS::Include\" directive. This directive can be present at any part of the template,\n    and not just within resources.\n    \"\"\"\n\n    for key, val in template_dict.items():\n        if key == \"Fn::Transform\":\n            if isinstance(val, dict) and val.get(\"Name\") == \"AWS::Include\":\n                path = val.get(\"Parameters\", {}).get(\"Location\", {})\n                updated_path = _resolve_relative_to(path, original_root, new_root)\n                if not updated_path:\n                    # This path does not need to get updated\n                    continue\n\n                val[\"Parameters\"][\"Location\"] = updated_path\n\n        # Recurse through all dictionary values\n        elif isinstance(val, dict):\n            _update_aws_include_relative_path(val, original_root, new_root)\n        elif isinstance(val, list):\n            for item in val:\n                if isinstance(item, dict):\n                    _update_aws_include_relative_path(item, original_root, new_root)\n\n    return template_dict\n\n\ndef _resolve_relative_to(path, original_root, new_root):\n    \"\"\"\n    If the given ``path`` is a relative path, then assume it is relative to ``original_root``. This method will\n    update the path to be resolve it relative to ``new_root`` and return.\n\n    Examples\n    -------\n        # Assume a file called template.txt at location /tmp/original/root/template.txt expressed as relative path\n        # We are trying to update it to be relative to /tmp/new/root instead of the /tmp/original/root\n        >>> result = _resolve_relative_to(\"template.txt\",  \\\n                                          \"/tmp/original/root\", \\\n                                          \"/tmp/new/root\")\n        >>> result\n        ../../original/root/template.txt\n\n    Returns\n    -------\n    Updated path if the given path is a relative path. None, if the path is not a relative path.\n    \"\"\"\n\n    if not isinstance(path, six.string_types) \\\n            or path.startswith(\"s3://\") \\\n            or os.path.isabs(path):\n        # Value is definitely NOT a relative path. It is either a S3 URi or Absolute path or not a string at all\n        return None\n\n    # Value is definitely a relative path. Change it relative to the destination directory\n    return os.path.relpath(\n        os.path.normpath(os.path.join(original_root, path)),  # Absolute original path w.r.t ``original_root``\n        new_root)  # Resolve the original path with respect to ``new_root``\n", "path": "samcli/commands/_utils/template.py"}], "after_files": [{"content": "\"\"\"\nUtilities to manipulate template\n\"\"\"\n\nimport os\nimport six\nimport yaml\n\ntry:\n    import pathlib\nexcept ImportError:\n    import pathlib2 as pathlib\n\nfrom samcli.yamlhelper import yaml_parse, yaml_dump\n\n\n_METADATA_WITH_LOCAL_PATHS = {\n    \"AWS::ServerlessRepo::Application\": [\"LicenseUrl\", \"ReadmeUrl\"]\n}\n\n_RESOURCES_WITH_LOCAL_PATHS = {\n    \"AWS::Serverless::Function\": [\"CodeUri\"],\n    \"AWS::Serverless::Api\": [\"DefinitionUri\"],\n    \"AWS::AppSync::GraphQLSchema\": [\"DefinitionS3Location\"],\n    \"AWS::AppSync::Resolver\": [\"RequestMappingTemplateS3Location\", \"ResponseMappingTemplateS3Location\"],\n    \"AWS::Lambda::Function\": [\"Code\"],\n    \"AWS::ApiGateway::RestApi\": [\"BodyS3Location\"],\n    \"AWS::ElasticBeanstalk::ApplicationVersion\": [\"SourceBundle\"],\n    \"AWS::CloudFormation::Stack\": [\"TemplateURL\"],\n    \"AWS::Serverless::Application\": [\"Location\"],\n    \"AWS::Lambda::LayerVersion\": [\"Content\"],\n    \"AWS::Serverless::LayerVersion\": [\"ContentUri\"]\n}\n\n\ndef get_template_data(template_file):\n    \"\"\"\n    Read the template file, parse it as JSON/YAML and return the template as a dictionary.\n\n    Parameters\n    ----------\n    template_file : string\n        Path to the template to read\n\n    Returns\n    -------\n    Template data as a dictionary\n    \"\"\"\n\n    if not pathlib.Path(template_file).exists():\n        raise ValueError(\"Template file not found at {}\".format(template_file))\n\n    with open(template_file, 'r') as fp:\n        try:\n            return yaml_parse(fp.read())\n        except (ValueError, yaml.YAMLError) as ex:\n            raise ValueError(\"Failed to parse template: {}\".format(str(ex)))\n\n\ndef move_template(src_template_path,\n                  dest_template_path,\n                  template_dict):\n    \"\"\"\n    Move the SAM/CloudFormation template from ``src_template_path`` to ``dest_template_path``. For convenience, this\n    method accepts a dictionary of template data ``template_dict`` that will be written to the destination instead of\n    reading from the source file.\n\n    SAM/CloudFormation template can contain certain properties whose value is a relative path to a local file/folder.\n    This path is always relative to the template's location. Before writing the template to ``dest_template_path`,\n    we will update these paths to be relative to the new location.\n\n    This methods updates resource properties supported by ``aws cloudformation package`` command:\n    https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html\n\n    You must use this method if you are reading a template from one location, modifying it, and writing it back to a\n    different location.\n\n    Parameters\n    ----------\n    src_template_path : str\n        Path to the original location of the template\n\n    dest_template_path : str\n        Path to the destination location where updated template should be written to\n\n    template_dict : dict\n        Dictionary containing template contents. This dictionary will be updated & written to ``dest`` location.\n    \"\"\"\n\n    original_root = os.path.dirname(src_template_path)\n    new_root = os.path.dirname(dest_template_path)\n\n    # Next up, we will be writing the template to a different location. Before doing so, we should\n    # update any relative paths in the template to be relative to the new location.\n    modified_template = _update_relative_paths(template_dict,\n                                               original_root,\n                                               new_root)\n\n    with open(dest_template_path, \"w\") as fp:\n        fp.write(yaml_dump(modified_template))\n\n\ndef _update_relative_paths(template_dict,\n                           original_root,\n                           new_root):\n    \"\"\"\n    SAM/CloudFormation template can contain certain properties whose value is a relative path to a local file/folder.\n    This path is usually relative to the template's location. If the template is being moved from original location\n    ``original_root`` to new location ``new_root``, use this method to update these paths to be\n    relative to ``new_root``.\n\n    After this method is complete, it is safe to write the template to ``new_root`` without\n    breaking any relative paths.\n\n    This methods updates resource properties supported by ``aws cloudformation package`` command:\n    https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html\n\n    If a property is either an absolute path or a S3 URI, this method will not update them.\n\n\n    Parameters\n    ----------\n    template_dict : dict\n        Dictionary containing template contents. This dictionary will be updated & written to ``dest`` location.\n\n    original_root : str\n        Path to the directory where all paths were originally set relative to. This is usually the directory\n        containing the template originally\n\n    new_root : str\n        Path to the new directory that all paths set relative to after this method completes.\n\n    Returns\n    -------\n    Updated dictionary\n\n    \"\"\"\n\n    for resource_type, properties in template_dict.get(\"Metadata\", {}).items():\n\n        if resource_type not in _METADATA_WITH_LOCAL_PATHS:\n            # Unknown resource. Skipping\n            continue\n\n        for path_prop_name in _METADATA_WITH_LOCAL_PATHS[resource_type]:\n            path = properties.get(path_prop_name)\n\n            updated_path = _resolve_relative_to(path, original_root, new_root)\n            if not updated_path:\n                # This path does not need to get updated\n                continue\n\n            properties[path_prop_name] = updated_path\n\n    for _, resource in template_dict.get(\"Resources\", {}).items():\n        resource_type = resource.get(\"Type\")\n\n        if resource_type not in _RESOURCES_WITH_LOCAL_PATHS:\n            # Unknown resource. Skipping\n            continue\n\n        for path_prop_name in _RESOURCES_WITH_LOCAL_PATHS[resource_type]:\n            properties = resource.get(\"Properties\", {})\n            path = properties.get(path_prop_name)\n\n            updated_path = _resolve_relative_to(path, original_root, new_root)\n            if not updated_path:\n                # This path does not need to get updated\n                continue\n\n            properties[path_prop_name] = updated_path\n\n    # AWS::Includes can be anywhere within the template dictionary. Hence we need to recurse through the\n    # dictionary in a separate method to find and update relative paths in there\n    template_dict = _update_aws_include_relative_path(template_dict, original_root, new_root)\n\n    return template_dict\n\n\ndef _update_aws_include_relative_path(template_dict, original_root, new_root):\n    \"\"\"\n    Update relative paths in \"AWS::Include\" directive. This directive can be present at any part of the template,\n    and not just within resources.\n    \"\"\"\n\n    for key, val in template_dict.items():\n        if key == \"Fn::Transform\":\n            if isinstance(val, dict) and val.get(\"Name\") == \"AWS::Include\":\n                path = val.get(\"Parameters\", {}).get(\"Location\", {})\n                updated_path = _resolve_relative_to(path, original_root, new_root)\n                if not updated_path:\n                    # This path does not need to get updated\n                    continue\n\n                val[\"Parameters\"][\"Location\"] = updated_path\n\n        # Recurse through all dictionary values\n        elif isinstance(val, dict):\n            _update_aws_include_relative_path(val, original_root, new_root)\n        elif isinstance(val, list):\n            for item in val:\n                if isinstance(item, dict):\n                    _update_aws_include_relative_path(item, original_root, new_root)\n\n    return template_dict\n\n\ndef _resolve_relative_to(path, original_root, new_root):\n    \"\"\"\n    If the given ``path`` is a relative path, then assume it is relative to ``original_root``. This method will\n    update the path to be resolve it relative to ``new_root`` and return.\n\n    Examples\n    -------\n        # Assume a file called template.txt at location /tmp/original/root/template.txt expressed as relative path\n        # We are trying to update it to be relative to /tmp/new/root instead of the /tmp/original/root\n        >>> result = _resolve_relative_to(\"template.txt\",  \\\n                                          \"/tmp/original/root\", \\\n                                          \"/tmp/new/root\")\n        >>> result\n        ../../original/root/template.txt\n\n    Returns\n    -------\n    Updated path if the given path is a relative path. None, if the path is not a relative path.\n    \"\"\"\n\n    if not isinstance(path, six.string_types) \\\n            or path.startswith(\"s3://\") \\\n            or os.path.isabs(path):\n        # Value is definitely NOT a relative path. It is either a S3 URi or Absolute path or not a string at all\n        return None\n\n    # Value is definitely a relative path. Change it relative to the destination directory\n    return os.path.relpath(\n        os.path.normpath(os.path.join(original_root, path)),  # Absolute original path w.r.t ``original_root``\n        new_root)  # Resolve the original path with respect to ``new_root``\n", "path": "samcli/commands/_utils/template.py"}]}