We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Consider implementing ++ operator for JSON
Possible behaviour:

```
db> SELECT to_json('[1,2]') ++ to_json('[3]') = to_json('[1,2,3]');
db> SELECT to_json('{"a": 1}') ++ to_json('{"b":2}') = to_json('{"a":1, "b":2}');
db> SELECT to_json('"123"') ++ to_json('"456"') = to_json('"123456"');
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `edb/buildmeta.py`
Content:
```
1 #
2 # This source file is part of the EdgeDB open source project.
3 #
4 # Copyright 2016-present MagicStack Inc. and the EdgeDB authors.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #     http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 
19 
20 from __future__ import annotations
21 from typing import *
22 
23 import hashlib
24 import importlib.util
25 import json
26 import logging
27 import os
28 import pathlib
29 import pickle
30 import re
31 import subprocess
32 import tempfile
33 
34 
35 from edb.common import debug
36 from edb.common import devmode
37 from edb.common import verutils
38 
39 
40 # Increment this whenever the database layout or stdlib changes.
41 EDGEDB_CATALOG_VERSION = 2021_10_19_00_00
42 
43 
44 class MetadataError(Exception):
45     pass
46 
47 
48 def get_build_metadata_value(prop: str) -> str:
49     env_val = os.environ.get(f'_EDGEDB_BUILDMETA_{prop}')
50     if env_val:
51         return env_val
52 
53     try:
54         from . import _buildmeta  # type: ignore
55         return getattr(_buildmeta, prop)
56     except (ImportError, AttributeError):
57         raise MetadataError(
58             f'could not find {prop} in EdgeDB distribution metadata') from None
59 
60 
61 def get_pg_config_path() -> pathlib.Path:
62     if devmode.is_in_dev_mode():
63         root = pathlib.Path(__file__).parent.parent
64         pg_config = (root / 'build' / 'postgres' /
65                      'install' / 'bin' / 'pg_config').resolve()
66         if not pg_config.is_file():
67             try:
68                 pg_config = pathlib.Path(
69                     get_build_metadata_value('PG_CONFIG_PATH'))
70             except MetadataError:
71                 pass
72 
73         if not pg_config.is_file():
74             raise MetadataError('DEV mode: Could not find PostgreSQL build, '
75                                 'run `pip install -e .`')
76 
77     else:
78         pg_config = pathlib.Path(
79             get_build_metadata_value('PG_CONFIG_PATH'))
80 
81         if not pg_config.is_file():
82             raise MetadataError(
83                 f'invalid pg_config path: {pg_config!r}: file does not exist '
84                 f'or is not a regular file')
85 
86     return pg_config
87 
88 
89 def get_runstate_path(data_dir: pathlib.Path) -> pathlib.Path:
90     if devmode.is_in_dev_mode():
91         return data_dir
92     else:
93         runstate_dir = get_build_metadata_value('RUNSTATE_DIR')
94         if runstate_dir is not None:
95             return pathlib.Path(runstate_dir)
96         else:
97             return data_dir
98 
99 
100 def get_shared_data_dir_path() -> pathlib.Path:
101     if devmode.is_in_dev_mode():
102         return devmode.get_dev_mode_cache_dir()  # type: ignore[return-value]
103     else:
104         return pathlib.Path(get_build_metadata_value('SHARED_DATA_DIR'))
105 
106 
107 def hash_dirs(
108     dirs: Sequence[Tuple[str, str]],
109     *,
110     extra_files: Optional[Sequence[Union[str, pathlib.Path]]]=None
111 ) -> bytes:
112     def hash_dir(dirname, ext, paths):
113         with os.scandir(dirname) as it:
114             for entry in it:
115                 if entry.is_file() and entry.name.endswith(ext):
116                     paths.append(entry.path)
117                 elif entry.is_dir():
118                     hash_dir(entry.path, ext, paths)
119 
120     paths: List[str] = []
121     for dirname, ext in dirs:
122         hash_dir(dirname, ext, paths)
123 
124     if extra_files:
125         for extra_file in extra_files:
126             if isinstance(extra_file, pathlib.Path):
127                 extra_file = str(extra_file.resolve())
128             paths.append(extra_file)
129 
130     h = hashlib.sha1()  # sha1 is the fastest one.
131     for path in sorted(paths):
132         with open(path, 'rb') as f:
133             h.update(f.read())
134 
135     return h.digest()
136 
137 
138 def read_data_cache(
139     cache_key: bytes,
140     path: str,
141     *,
142     pickled: bool=True,
143     source_dir: Optional[pathlib.Path] = None,
144 ) -> Any:
145     if source_dir is None:
146         source_dir = get_shared_data_dir_path()
147     full_path = source_dir / path
148 
149     if full_path.exists():
150         with open(full_path, 'rb') as f:
151             src_hash = f.read(len(cache_key))
152             if src_hash == cache_key or debug.flags.bootstrap_cache_yolo:
153                 if pickled:
154                     data = f.read()
155                     try:
156                         return pickle.loads(data)
157                     except Exception:
158                         logging.exception(f'could not unpickle {path}')
159                 else:
160                     return f.read()
161 
162 
163 def write_data_cache(
164     obj: Any,
165     cache_key: bytes,
166     path: str,
167     *,
168     pickled: bool = True,
169     target_dir: Optional[pathlib.Path] = None,
170 ):
171     if target_dir is None:
172         target_dir = get_shared_data_dir_path()
173     full_path = target_dir / path
174 
175     try:
176         with tempfile.NamedTemporaryFile(
177                 mode='wb', dir=full_path.parent, delete=False) as f:
178             f.write(cache_key)
179             if pickled:
180                 pickle.dump(obj, file=f, protocol=pickle.HIGHEST_PROTOCOL)
181             else:
182                 f.write(obj)
183     except Exception:
184         try:
185             os.unlink(f.name)
186         except OSError:
187             pass
188         finally:
189             raise
190     else:
191         os.rename(f.name, full_path)
192 
193 
194 def get_version() -> verutils.Version:
195     if devmode.is_in_dev_mode():
196         root = pathlib.Path(__file__).parent.parent.resolve()
197         version = verutils.parse_version(get_version_from_scm(root))
198     else:
199         vertuple: List[Any] = list(get_build_metadata_value('VERSION'))
200         vertuple[2] = verutils.VersionStage(vertuple[2])
201         version = verutils.Version(*vertuple)
202 
203     return version
204 
205 
206 _version_dict: Optional[Mapping[str, Any]] = None
207 
208 
209 def get_version_dict() -> Mapping[str, Any]:
210     global _version_dict
211 
212     if _version_dict is None:
213         ver = get_version()
214         _version_dict = {
215             'major': ver.major,
216             'minor': ver.minor,
217             'stage': ver.stage.name.lower(),
218             'stage_no': ver.stage_no,
219             'local': tuple(ver.local) if ver.local else (),
220         }
221 
222     return _version_dict
223 
224 
225 _version_json: Optional[str] = None
226 
227 
228 def get_version_json() -> str:
229     global _version_json
230     if _version_json is None:
231         _version_json = json.dumps(get_version_dict())
232     return _version_json
233 
234 
235 def get_version_from_scm(root: pathlib.Path) -> str:
236     pretend = os.environ.get('SETUPTOOLS_SCM_PRETEND_VERSION')
237     if pretend:
238         return pretend
239 
240     posint = r'(0|[1-9]\d*)'
241     pep440_version_re = re.compile(
242         rf"""
243         ^
244         (?P<major>{posint})
245         \.
246         (?P<minor>{posint})
247         (
248             \.
249             (?P<micro>{posint})
250         )?
251         (
252             (?P<prekind>a|b|rc)
253             (?P<preval>{posint})
254         )?
255         $
256         """,
257         re.X,
258     )
259 
260     proc = subprocess.run(
261         ['git', 'tag', '--list', 'v*'],
262         stdout=subprocess.PIPE,
263         universal_newlines=True,
264         check=True,
265         cwd=root,
266     )
267     all_tags = {
268         v[1:]
269         for v in proc.stdout.strip().split('\n')
270         if pep440_version_re.match(v[1:])
271     }
272 
273     proc = subprocess.run(
274         ['git', 'tag', '--points-at', 'HEAD'],
275         stdout=subprocess.PIPE,
276         universal_newlines=True,
277         check=True,
278         cwd=root,
279     )
280     head_tags = {
281         v[1:]
282         for v in proc.stdout.strip().split('\n')
283         if pep440_version_re.match(v[1:])
284     }
285 
286     if all_tags & head_tags:
287         tag = max(head_tags)
288     else:
289         tag = max(all_tags)
290 
291     m = pep440_version_re.match(tag)
292     assert m is not None
293     major = m.group('major')
294     minor = m.group('minor')
295     micro = m.group('micro') or ''
296     microkind = '.' if micro else ''
297     prekind = m.group('prekind') or ''
298     preval = m.group('preval') or ''
299 
300     if os.environ.get("EDGEDB_BUILD_IS_RELEASE"):
301         # Release build.
302         ver = f'{major}.{minor}{microkind}{micro}{prekind}{preval}'
303     else:
304         # Dev/nightly build.
305         if prekind and preval:
306             preval = str(int(preval) + 1)
307         elif micro:
308             micro = str(int(micro) + 1)
309         else:
310             minor = str(int(minor) + 1)
311 
312         incremented_ver = f'{major}.{minor}{microkind}{micro}{prekind}{preval}'
313 
314         proc = subprocess.run(
315             ['git', 'rev-list', '--count', 'HEAD'],
316             stdout=subprocess.PIPE,
317             universal_newlines=True,
318             check=True,
319             cwd=root,
320         )
321         commits_on_branch = proc.stdout.strip()
322         ver = f'{incremented_ver}.dev{commits_on_branch}'
323 
324     proc = subprocess.run(
325         ['git', 'rev-parse', '--verify', '--quiet', 'HEAD'],
326         stdout=subprocess.PIPE,
327         universal_newlines=True,
328         check=True,
329         cwd=root,
330     )
331     commitish = proc.stdout.strip()
332 
333     env = dict(os.environ)
334     env['TZ'] = 'UTC'
335     proc = subprocess.run(
336         ['git', 'show', '-s', '--format=%cd',
337          '--date=format-local:%Y%m%d%H', commitish],
338         stdout=subprocess.PIPE,
339         universal_newlines=True,
340         check=True,
341         cwd=root,
342         env=env,
343     )
344     rev_date = proc.stdout.strip()
345 
346     catver = EDGEDB_CATALOG_VERSION
347     return f'{ver}+d{rev_date}.g{commitish[:9]}.cv{catver}'
348 
349 
350 def get_cache_src_dirs():
351     find_spec = importlib.util.find_spec
352 
353     edgeql = pathlib.Path(find_spec('edb.edgeql').origin).parent
354     return (
355         (pathlib.Path(find_spec('edb.schema').origin).parent, '.py'),
356         (edgeql / 'compiler', '.py'),
357         (edgeql / 'parser', '.py'),
358         (pathlib.Path(find_spec('edb.lib').origin).parent, '.edgeql'),
359         (pathlib.Path(find_spec('edb.pgsql.metaschema').origin).parent, '.py'),
360     )
361 
362 
363 def get_default_tenant_id() -> str:
364     catver = EDGEDB_CATALOG_VERSION
365     return f'V{catver:x}'
366
```
--- 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/edb/buildmeta.py b/edb/buildmeta.py
--- a/edb/buildmeta.py
+++ b/edb/buildmeta.py
@@ -38,7 +38,7 @@
 
 
 # Increment this whenever the database layout or stdlib changes.
-EDGEDB_CATALOG_VERSION = 2021_10_19_00_00
+EDGEDB_CATALOG_VERSION = 2021_10_24_00_00
 
 
 class MetadataError(Exception):

{"golden_diff": "diff --git a/edb/buildmeta.py b/edb/buildmeta.py\n--- a/edb/buildmeta.py\n+++ b/edb/buildmeta.py\n@@ -38,7 +38,7 @@\n \n \n # Increment this whenever the database layout or stdlib changes.\n-EDGEDB_CATALOG_VERSION = 2021_10_19_00_00\n+EDGEDB_CATALOG_VERSION = 2021_10_24_00_00\n \n \n class MetadataError(Exception):\n", "issue": "Consider implementing ++ operator for JSON\nPossible behaviour:\r\n\r\n```\r\ndb> SELECT to_json('[1,2]') ++ to_json('[3]') = to_json('[1,2,3]');\r\ndb> SELECT to_json('{\"a\": 1}') ++ to_json('{\"b\":2}') = to_json('{\"a\":1, \"b\":2}');\r\ndb> SELECT to_json('\"123\"') ++ to_json('\"456\"') = to_json('\"123456\"');\r\n```\n", "before_files": [{"content": "#\n# This source file is part of the EdgeDB open source project.\n#\n# Copyright 2016-present MagicStack Inc. and the EdgeDB authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n\nfrom __future__ import annotations\nfrom typing import *\n\nimport hashlib\nimport importlib.util\nimport json\nimport logging\nimport os\nimport pathlib\nimport pickle\nimport re\nimport subprocess\nimport tempfile\n\n\nfrom edb.common import debug\nfrom edb.common import devmode\nfrom edb.common import verutils\n\n\n# Increment this whenever the database layout or stdlib changes.\nEDGEDB_CATALOG_VERSION = 2021_10_19_00_00\n\n\nclass MetadataError(Exception):\n    pass\n\n\ndef get_build_metadata_value(prop: str) -> str:\n    env_val = os.environ.get(f'_EDGEDB_BUILDMETA_{prop}')\n    if env_val:\n        return env_val\n\n    try:\n        from . import _buildmeta  # type: ignore\n        return getattr(_buildmeta, prop)\n    except (ImportError, AttributeError):\n        raise MetadataError(\n            f'could not find {prop} in EdgeDB distribution metadata') from None\n\n\ndef get_pg_config_path() -> pathlib.Path:\n    if devmode.is_in_dev_mode():\n        root = pathlib.Path(__file__).parent.parent\n        pg_config = (root / 'build' / 'postgres' /\n                     'install' / 'bin' / 'pg_config').resolve()\n        if not pg_config.is_file():\n            try:\n                pg_config = pathlib.Path(\n                    get_build_metadata_value('PG_CONFIG_PATH'))\n            except MetadataError:\n                pass\n\n        if not pg_config.is_file():\n            raise MetadataError('DEV mode: Could not find PostgreSQL build, '\n                                'run `pip install -e .`')\n\n    else:\n        pg_config = pathlib.Path(\n            get_build_metadata_value('PG_CONFIG_PATH'))\n\n        if not pg_config.is_file():\n            raise MetadataError(\n                f'invalid pg_config path: {pg_config!r}: file does not exist '\n                f'or is not a regular file')\n\n    return pg_config\n\n\ndef get_runstate_path(data_dir: pathlib.Path) -> pathlib.Path:\n    if devmode.is_in_dev_mode():\n        return data_dir\n    else:\n        runstate_dir = get_build_metadata_value('RUNSTATE_DIR')\n        if runstate_dir is not None:\n            return pathlib.Path(runstate_dir)\n        else:\n            return data_dir\n\n\ndef get_shared_data_dir_path() -> pathlib.Path:\n    if devmode.is_in_dev_mode():\n        return devmode.get_dev_mode_cache_dir()  # type: ignore[return-value]\n    else:\n        return pathlib.Path(get_build_metadata_value('SHARED_DATA_DIR'))\n\n\ndef hash_dirs(\n    dirs: Sequence[Tuple[str, str]],\n    *,\n    extra_files: Optional[Sequence[Union[str, pathlib.Path]]]=None\n) -> bytes:\n    def hash_dir(dirname, ext, paths):\n        with os.scandir(dirname) as it:\n            for entry in it:\n                if entry.is_file() and entry.name.endswith(ext):\n                    paths.append(entry.path)\n                elif entry.is_dir():\n                    hash_dir(entry.path, ext, paths)\n\n    paths: List[str] = []\n    for dirname, ext in dirs:\n        hash_dir(dirname, ext, paths)\n\n    if extra_files:\n        for extra_file in extra_files:\n            if isinstance(extra_file, pathlib.Path):\n                extra_file = str(extra_file.resolve())\n            paths.append(extra_file)\n\n    h = hashlib.sha1()  # sha1 is the fastest one.\n    for path in sorted(paths):\n        with open(path, 'rb') as f:\n            h.update(f.read())\n\n    return h.digest()\n\n\ndef read_data_cache(\n    cache_key: bytes,\n    path: str,\n    *,\n    pickled: bool=True,\n    source_dir: Optional[pathlib.Path] = None,\n) -> Any:\n    if source_dir is None:\n        source_dir = get_shared_data_dir_path()\n    full_path = source_dir / path\n\n    if full_path.exists():\n        with open(full_path, 'rb') as f:\n            src_hash = f.read(len(cache_key))\n            if src_hash == cache_key or debug.flags.bootstrap_cache_yolo:\n                if pickled:\n                    data = f.read()\n                    try:\n                        return pickle.loads(data)\n                    except Exception:\n                        logging.exception(f'could not unpickle {path}')\n                else:\n                    return f.read()\n\n\ndef write_data_cache(\n    obj: Any,\n    cache_key: bytes,\n    path: str,\n    *,\n    pickled: bool = True,\n    target_dir: Optional[pathlib.Path] = None,\n):\n    if target_dir is None:\n        target_dir = get_shared_data_dir_path()\n    full_path = target_dir / path\n\n    try:\n        with tempfile.NamedTemporaryFile(\n                mode='wb', dir=full_path.parent, delete=False) as f:\n            f.write(cache_key)\n            if pickled:\n                pickle.dump(obj, file=f, protocol=pickle.HIGHEST_PROTOCOL)\n            else:\n                f.write(obj)\n    except Exception:\n        try:\n            os.unlink(f.name)\n        except OSError:\n            pass\n        finally:\n            raise\n    else:\n        os.rename(f.name, full_path)\n\n\ndef get_version() -> verutils.Version:\n    if devmode.is_in_dev_mode():\n        root = pathlib.Path(__file__).parent.parent.resolve()\n        version = verutils.parse_version(get_version_from_scm(root))\n    else:\n        vertuple: List[Any] = list(get_build_metadata_value('VERSION'))\n        vertuple[2] = verutils.VersionStage(vertuple[2])\n        version = verutils.Version(*vertuple)\n\n    return version\n\n\n_version_dict: Optional[Mapping[str, Any]] = None\n\n\ndef get_version_dict() -> Mapping[str, Any]:\n    global _version_dict\n\n    if _version_dict is None:\n        ver = get_version()\n        _version_dict = {\n            'major': ver.major,\n            'minor': ver.minor,\n            'stage': ver.stage.name.lower(),\n            'stage_no': ver.stage_no,\n            'local': tuple(ver.local) if ver.local else (),\n        }\n\n    return _version_dict\n\n\n_version_json: Optional[str] = None\n\n\ndef get_version_json() -> str:\n    global _version_json\n    if _version_json is None:\n        _version_json = json.dumps(get_version_dict())\n    return _version_json\n\n\ndef get_version_from_scm(root: pathlib.Path) -> str:\n    pretend = os.environ.get('SETUPTOOLS_SCM_PRETEND_VERSION')\n    if pretend:\n        return pretend\n\n    posint = r'(0|[1-9]\\d*)'\n    pep440_version_re = re.compile(\n        rf\"\"\"\n        ^\n        (?P<major>{posint})\n        \\.\n        (?P<minor>{posint})\n        (\n            \\.\n            (?P<micro>{posint})\n        )?\n        (\n            (?P<prekind>a|b|rc)\n            (?P<preval>{posint})\n        )?\n        $\n        \"\"\",\n        re.X,\n    )\n\n    proc = subprocess.run(\n        ['git', 'tag', '--list', 'v*'],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n    )\n    all_tags = {\n        v[1:]\n        for v in proc.stdout.strip().split('\\n')\n        if pep440_version_re.match(v[1:])\n    }\n\n    proc = subprocess.run(\n        ['git', 'tag', '--points-at', 'HEAD'],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n    )\n    head_tags = {\n        v[1:]\n        for v in proc.stdout.strip().split('\\n')\n        if pep440_version_re.match(v[1:])\n    }\n\n    if all_tags & head_tags:\n        tag = max(head_tags)\n    else:\n        tag = max(all_tags)\n\n    m = pep440_version_re.match(tag)\n    assert m is not None\n    major = m.group('major')\n    minor = m.group('minor')\n    micro = m.group('micro') or ''\n    microkind = '.' if micro else ''\n    prekind = m.group('prekind') or ''\n    preval = m.group('preval') or ''\n\n    if os.environ.get(\"EDGEDB_BUILD_IS_RELEASE\"):\n        # Release build.\n        ver = f'{major}.{minor}{microkind}{micro}{prekind}{preval}'\n    else:\n        # Dev/nightly build.\n        if prekind and preval:\n            preval = str(int(preval) + 1)\n        elif micro:\n            micro = str(int(micro) + 1)\n        else:\n            minor = str(int(minor) + 1)\n\n        incremented_ver = f'{major}.{minor}{microkind}{micro}{prekind}{preval}'\n\n        proc = subprocess.run(\n            ['git', 'rev-list', '--count', 'HEAD'],\n            stdout=subprocess.PIPE,\n            universal_newlines=True,\n            check=True,\n            cwd=root,\n        )\n        commits_on_branch = proc.stdout.strip()\n        ver = f'{incremented_ver}.dev{commits_on_branch}'\n\n    proc = subprocess.run(\n        ['git', 'rev-parse', '--verify', '--quiet', 'HEAD'],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n    )\n    commitish = proc.stdout.strip()\n\n    env = dict(os.environ)\n    env['TZ'] = 'UTC'\n    proc = subprocess.run(\n        ['git', 'show', '-s', '--format=%cd',\n         '--date=format-local:%Y%m%d%H', commitish],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n        env=env,\n    )\n    rev_date = proc.stdout.strip()\n\n    catver = EDGEDB_CATALOG_VERSION\n    return f'{ver}+d{rev_date}.g{commitish[:9]}.cv{catver}'\n\n\ndef get_cache_src_dirs():\n    find_spec = importlib.util.find_spec\n\n    edgeql = pathlib.Path(find_spec('edb.edgeql').origin).parent\n    return (\n        (pathlib.Path(find_spec('edb.schema').origin).parent, '.py'),\n        (edgeql / 'compiler', '.py'),\n        (edgeql / 'parser', '.py'),\n        (pathlib.Path(find_spec('edb.lib').origin).parent, '.edgeql'),\n        (pathlib.Path(find_spec('edb.pgsql.metaschema').origin).parent, '.py'),\n    )\n\n\ndef get_default_tenant_id() -> str:\n    catver = EDGEDB_CATALOG_VERSION\n    return f'V{catver:x}'\n", "path": "edb/buildmeta.py"}], "after_files": [{"content": "#\n# This source file is part of the EdgeDB open source project.\n#\n# Copyright 2016-present MagicStack Inc. and the EdgeDB authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n\nfrom __future__ import annotations\nfrom typing import *\n\nimport hashlib\nimport importlib.util\nimport json\nimport logging\nimport os\nimport pathlib\nimport pickle\nimport re\nimport subprocess\nimport tempfile\n\n\nfrom edb.common import debug\nfrom edb.common import devmode\nfrom edb.common import verutils\n\n\n# Increment this whenever the database layout or stdlib changes.\nEDGEDB_CATALOG_VERSION = 2021_10_24_00_00\n\n\nclass MetadataError(Exception):\n    pass\n\n\ndef get_build_metadata_value(prop: str) -> str:\n    env_val = os.environ.get(f'_EDGEDB_BUILDMETA_{prop}')\n    if env_val:\n        return env_val\n\n    try:\n        from . import _buildmeta  # type: ignore\n        return getattr(_buildmeta, prop)\n    except (ImportError, AttributeError):\n        raise MetadataError(\n            f'could not find {prop} in EdgeDB distribution metadata') from None\n\n\ndef get_pg_config_path() -> pathlib.Path:\n    if devmode.is_in_dev_mode():\n        root = pathlib.Path(__file__).parent.parent\n        pg_config = (root / 'build' / 'postgres' /\n                     'install' / 'bin' / 'pg_config').resolve()\n        if not pg_config.is_file():\n            try:\n                pg_config = pathlib.Path(\n                    get_build_metadata_value('PG_CONFIG_PATH'))\n            except MetadataError:\n                pass\n\n        if not pg_config.is_file():\n            raise MetadataError('DEV mode: Could not find PostgreSQL build, '\n                                'run `pip install -e .`')\n\n    else:\n        pg_config = pathlib.Path(\n            get_build_metadata_value('PG_CONFIG_PATH'))\n\n        if not pg_config.is_file():\n            raise MetadataError(\n                f'invalid pg_config path: {pg_config!r}: file does not exist '\n                f'or is not a regular file')\n\n    return pg_config\n\n\ndef get_runstate_path(data_dir: pathlib.Path) -> pathlib.Path:\n    if devmode.is_in_dev_mode():\n        return data_dir\n    else:\n        runstate_dir = get_build_metadata_value('RUNSTATE_DIR')\n        if runstate_dir is not None:\n            return pathlib.Path(runstate_dir)\n        else:\n            return data_dir\n\n\ndef get_shared_data_dir_path() -> pathlib.Path:\n    if devmode.is_in_dev_mode():\n        return devmode.get_dev_mode_cache_dir()  # type: ignore[return-value]\n    else:\n        return pathlib.Path(get_build_metadata_value('SHARED_DATA_DIR'))\n\n\ndef hash_dirs(\n    dirs: Sequence[Tuple[str, str]],\n    *,\n    extra_files: Optional[Sequence[Union[str, pathlib.Path]]]=None\n) -> bytes:\n    def hash_dir(dirname, ext, paths):\n        with os.scandir(dirname) as it:\n            for entry in it:\n                if entry.is_file() and entry.name.endswith(ext):\n                    paths.append(entry.path)\n                elif entry.is_dir():\n                    hash_dir(entry.path, ext, paths)\n\n    paths: List[str] = []\n    for dirname, ext in dirs:\n        hash_dir(dirname, ext, paths)\n\n    if extra_files:\n        for extra_file in extra_files:\n            if isinstance(extra_file, pathlib.Path):\n                extra_file = str(extra_file.resolve())\n            paths.append(extra_file)\n\n    h = hashlib.sha1()  # sha1 is the fastest one.\n    for path in sorted(paths):\n        with open(path, 'rb') as f:\n            h.update(f.read())\n\n    return h.digest()\n\n\ndef read_data_cache(\n    cache_key: bytes,\n    path: str,\n    *,\n    pickled: bool=True,\n    source_dir: Optional[pathlib.Path] = None,\n) -> Any:\n    if source_dir is None:\n        source_dir = get_shared_data_dir_path()\n    full_path = source_dir / path\n\n    if full_path.exists():\n        with open(full_path, 'rb') as f:\n            src_hash = f.read(len(cache_key))\n            if src_hash == cache_key or debug.flags.bootstrap_cache_yolo:\n                if pickled:\n                    data = f.read()\n                    try:\n                        return pickle.loads(data)\n                    except Exception:\n                        logging.exception(f'could not unpickle {path}')\n                else:\n                    return f.read()\n\n\ndef write_data_cache(\n    obj: Any,\n    cache_key: bytes,\n    path: str,\n    *,\n    pickled: bool = True,\n    target_dir: Optional[pathlib.Path] = None,\n):\n    if target_dir is None:\n        target_dir = get_shared_data_dir_path()\n    full_path = target_dir / path\n\n    try:\n        with tempfile.NamedTemporaryFile(\n                mode='wb', dir=full_path.parent, delete=False) as f:\n            f.write(cache_key)\n            if pickled:\n                pickle.dump(obj, file=f, protocol=pickle.HIGHEST_PROTOCOL)\n            else:\n                f.write(obj)\n    except Exception:\n        try:\n            os.unlink(f.name)\n        except OSError:\n            pass\n        finally:\n            raise\n    else:\n        os.rename(f.name, full_path)\n\n\ndef get_version() -> verutils.Version:\n    if devmode.is_in_dev_mode():\n        root = pathlib.Path(__file__).parent.parent.resolve()\n        version = verutils.parse_version(get_version_from_scm(root))\n    else:\n        vertuple: List[Any] = list(get_build_metadata_value('VERSION'))\n        vertuple[2] = verutils.VersionStage(vertuple[2])\n        version = verutils.Version(*vertuple)\n\n    return version\n\n\n_version_dict: Optional[Mapping[str, Any]] = None\n\n\ndef get_version_dict() -> Mapping[str, Any]:\n    global _version_dict\n\n    if _version_dict is None:\n        ver = get_version()\n        _version_dict = {\n            'major': ver.major,\n            'minor': ver.minor,\n            'stage': ver.stage.name.lower(),\n            'stage_no': ver.stage_no,\n            'local': tuple(ver.local) if ver.local else (),\n        }\n\n    return _version_dict\n\n\n_version_json: Optional[str] = None\n\n\ndef get_version_json() -> str:\n    global _version_json\n    if _version_json is None:\n        _version_json = json.dumps(get_version_dict())\n    return _version_json\n\n\ndef get_version_from_scm(root: pathlib.Path) -> str:\n    pretend = os.environ.get('SETUPTOOLS_SCM_PRETEND_VERSION')\n    if pretend:\n        return pretend\n\n    posint = r'(0|[1-9]\\d*)'\n    pep440_version_re = re.compile(\n        rf\"\"\"\n        ^\n        (?P<major>{posint})\n        \\.\n        (?P<minor>{posint})\n        (\n            \\.\n            (?P<micro>{posint})\n        )?\n        (\n            (?P<prekind>a|b|rc)\n            (?P<preval>{posint})\n        )?\n        $\n        \"\"\",\n        re.X,\n    )\n\n    proc = subprocess.run(\n        ['git', 'tag', '--list', 'v*'],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n    )\n    all_tags = {\n        v[1:]\n        for v in proc.stdout.strip().split('\\n')\n        if pep440_version_re.match(v[1:])\n    }\n\n    proc = subprocess.run(\n        ['git', 'tag', '--points-at', 'HEAD'],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n    )\n    head_tags = {\n        v[1:]\n        for v in proc.stdout.strip().split('\\n')\n        if pep440_version_re.match(v[1:])\n    }\n\n    if all_tags & head_tags:\n        tag = max(head_tags)\n    else:\n        tag = max(all_tags)\n\n    m = pep440_version_re.match(tag)\n    assert m is not None\n    major = m.group('major')\n    minor = m.group('minor')\n    micro = m.group('micro') or ''\n    microkind = '.' if micro else ''\n    prekind = m.group('prekind') or ''\n    preval = m.group('preval') or ''\n\n    if os.environ.get(\"EDGEDB_BUILD_IS_RELEASE\"):\n        # Release build.\n        ver = f'{major}.{minor}{microkind}{micro}{prekind}{preval}'\n    else:\n        # Dev/nightly build.\n        if prekind and preval:\n            preval = str(int(preval) + 1)\n        elif micro:\n            micro = str(int(micro) + 1)\n        else:\n            minor = str(int(minor) + 1)\n\n        incremented_ver = f'{major}.{minor}{microkind}{micro}{prekind}{preval}'\n\n        proc = subprocess.run(\n            ['git', 'rev-list', '--count', 'HEAD'],\n            stdout=subprocess.PIPE,\n            universal_newlines=True,\n            check=True,\n            cwd=root,\n        )\n        commits_on_branch = proc.stdout.strip()\n        ver = f'{incremented_ver}.dev{commits_on_branch}'\n\n    proc = subprocess.run(\n        ['git', 'rev-parse', '--verify', '--quiet', 'HEAD'],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n    )\n    commitish = proc.stdout.strip()\n\n    env = dict(os.environ)\n    env['TZ'] = 'UTC'\n    proc = subprocess.run(\n        ['git', 'show', '-s', '--format=%cd',\n         '--date=format-local:%Y%m%d%H', commitish],\n        stdout=subprocess.PIPE,\n        universal_newlines=True,\n        check=True,\n        cwd=root,\n        env=env,\n    )\n    rev_date = proc.stdout.strip()\n\n    catver = EDGEDB_CATALOG_VERSION\n    return f'{ver}+d{rev_date}.g{commitish[:9]}.cv{catver}'\n\n\ndef get_cache_src_dirs():\n    find_spec = importlib.util.find_spec\n\n    edgeql = pathlib.Path(find_spec('edb.edgeql').origin).parent\n    return (\n        (pathlib.Path(find_spec('edb.schema').origin).parent, '.py'),\n        (edgeql / 'compiler', '.py'),\n        (edgeql / 'parser', '.py'),\n        (pathlib.Path(find_spec('edb.lib').origin).parent, '.edgeql'),\n        (pathlib.Path(find_spec('edb.pgsql.metaschema').origin).parent, '.py'),\n    )\n\n\ndef get_default_tenant_id() -> str:\n    catver = EDGEDB_CATALOG_VERSION\n    return f'V{catver:x}'\n", "path": "edb/buildmeta.py"}]}