We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
provision: Clean up interface for template_database_status
Following 84edb5c5162e9299ab5fb6a0a59c402484caa98c, it's clear that we should have a cleaner database for how the arguments to `template_database_status` are passed to correctly check whether the target database (whether zulip_test_template, used by `test-backend`, or the ).  I think we could do significantly better by defining a class or TypedDict defining the settings for the `zulip_test_template` and `zulip` databases and accessing those. (Or maybe just having there be a single argument for which database we're checking?).  

Fundamentally, there's only two valid ways to call `template_database_status`, so it shouldn't take like 5 arguments with defaults, it should take one argument that specifies which database we want to access.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tools/lib/provision_inner.py`
Content:
```
1 #!/usr/bin/env python3
2 import os
3 import sys
4 import argparse
5 import glob
6 import shutil
7 
8 ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
9 
10 sys.path.append(ZULIP_PATH)
11 from scripts.lib.zulip_tools import run, run_as_root, OKBLUE, ENDC, \
12     get_dev_uuid_var_path, file_or_package_hash_updated
13 
14 from version import PROVISION_VERSION
15 
16 from tools.setup.generate_zulip_bots_static_files import generate_zulip_bots_static_files
17 
18 VENV_PATH = "/srv/zulip-py3-venv"
19 VAR_DIR_PATH = os.path.join(ZULIP_PATH, 'var')
20 LOG_DIR_PATH = os.path.join(VAR_DIR_PATH, 'log')
21 UPLOAD_DIR_PATH = os.path.join(VAR_DIR_PATH, 'uploads')
22 TEST_UPLOAD_DIR_PATH = os.path.join(VAR_DIR_PATH, 'test_uploads')
23 COVERAGE_DIR_PATH = os.path.join(VAR_DIR_PATH, 'coverage')
24 NODE_TEST_COVERAGE_DIR_PATH = os.path.join(VAR_DIR_PATH, 'node-coverage')
25 XUNIT_XML_TEST_RESULTS_DIR_PATH = os.path.join(VAR_DIR_PATH, 'xunit-test-results')
26 
27 is_travis = 'TRAVIS' in os.environ
28 
29 # TODO: De-duplicate this with emoji_dump.py
30 EMOJI_CACHE_PATH = "/srv/zulip-emoji-cache"
31 if is_travis:
32     # In Travis CI, we don't have root access
33     EMOJI_CACHE_PATH = "/home/travis/zulip-emoji-cache"
34 
35 UUID_VAR_PATH = get_dev_uuid_var_path()
36 
37 def setup_shell_profile(shell_profile):
38     # type: (str) -> None
39     shell_profile_path = os.path.expanduser(shell_profile)
40 
41     def write_command(command):
42         # type: (str) -> None
43         if os.path.exists(shell_profile_path):
44             with open(shell_profile_path, 'r') as shell_profile_file:
45                 lines = [line.strip() for line in shell_profile_file.readlines()]
46             if command not in lines:
47                 with open(shell_profile_path, 'a+') as shell_profile_file:
48                     shell_profile_file.writelines(command + '\n')
49         else:
50             with open(shell_profile_path, 'w') as shell_profile_file:
51                 shell_profile_file.writelines(command + '\n')
52 
53     source_activate_command = "source " + os.path.join(VENV_PATH, "bin", "activate")
54     write_command(source_activate_command)
55     if os.path.exists('/srv/zulip'):
56         write_command('cd /srv/zulip')
57 
58 def setup_bash_profile() -> None:
59     """Select a bash profile file to add setup code to."""
60 
61     BASH_PROFILES = [
62         os.path.expanduser(p) for p in
63         ("~/.bash_profile", "~/.bash_login", "~/.profile")
64     ]
65 
66     def clear_old_profile() -> None:
67         # An earlier version of this script would output a fresh .bash_profile
68         # even though a .profile existed in the image used. As a convenience to
69         # existing developers (and, perhaps, future developers git-bisecting the
70         # provisioning scripts), check for this situation, and blow away the
71         # created .bash_profile if one is found.
72 
73         BASH_PROFILE = BASH_PROFILES[0]
74         DOT_PROFILE = BASH_PROFILES[2]
75         OLD_PROFILE_TEXT = "source /srv/zulip-py3-venv/bin/activate\n" + \
76             "cd /srv/zulip\n"
77 
78         if os.path.exists(DOT_PROFILE):
79             try:
80                 with open(BASH_PROFILE, "r") as f:
81                     profile_contents = f.read()
82                 if profile_contents == OLD_PROFILE_TEXT:
83                     os.unlink(BASH_PROFILE)
84             except FileNotFoundError:
85                 pass
86 
87     clear_old_profile()
88 
89     for candidate_profile in BASH_PROFILES:
90         if os.path.exists(candidate_profile):
91             setup_shell_profile(candidate_profile)
92             break
93     else:
94         # no existing bash profile found; claim .bash_profile
95         setup_shell_profile(BASH_PROFILES[0])
96 
97 def main(options: argparse.Namespace) -> int:
98     setup_bash_profile()
99     setup_shell_profile('~/.zprofile')
100 
101     # This needs to happen before anything that imports zproject.settings.
102     run(["scripts/setup/generate_secrets.py", "--development"])
103 
104     # create log directory `zulip/var/log`
105     os.makedirs(LOG_DIR_PATH, exist_ok=True)
106     # create upload directory `var/uploads`
107     os.makedirs(UPLOAD_DIR_PATH, exist_ok=True)
108     # create test upload directory `var/test_upload`
109     os.makedirs(TEST_UPLOAD_DIR_PATH, exist_ok=True)
110     # create coverage directory `var/coverage`
111     os.makedirs(COVERAGE_DIR_PATH, exist_ok=True)
112     # create linecoverage directory `var/node-coverage`
113     os.makedirs(NODE_TEST_COVERAGE_DIR_PATH, exist_ok=True)
114     # create XUnit XML test results directory`var/xunit-test-results`
115     os.makedirs(XUNIT_XML_TEST_RESULTS_DIR_PATH, exist_ok=True)
116 
117     # The `build_emoji` script requires `emoji-datasource` package
118     # which we install via npm; thus this step is after installing npm
119     # packages.
120     if not os.access(EMOJI_CACHE_PATH, os.W_OK):
121         run_as_root(["mkdir", "-p", EMOJI_CACHE_PATH])
122         run_as_root(["chown", "%s:%s" % (os.getuid(), os.getgid()), EMOJI_CACHE_PATH])
123     run(["tools/setup/emoji/build_emoji"])
124 
125     # copy over static files from the zulip_bots package
126     generate_zulip_bots_static_files()
127 
128     build_pygments_data_paths = ["tools/setup/build_pygments_data", "tools/setup/lang.json"]
129     from pygments import __version__ as pygments_version
130     if file_or_package_hash_updated(build_pygments_data_paths, "build_pygments_data_hash", options.is_force,
131                                     [pygments_version]):
132         run(["tools/setup/build_pygments_data"])
133     else:
134         print("No need to run `tools/setup/build_pygments_data`.")
135 
136     update_authors_json_paths = ["tools/update-authors-json", "zerver/tests/fixtures/authors.json"]
137     if file_or_package_hash_updated(update_authors_json_paths, "update_authors_json_hash", options.is_force):
138         run(["tools/update-authors-json", "--use-fixture"])
139     else:
140         print("No need to run `tools/update-authors-json`.")
141 
142     email_source_paths = ["scripts/setup/inline-email-css", "templates/zerver/emails/email.css"]
143     email_source_paths += glob.glob('templates/zerver/emails/*.source.html')
144     if file_or_package_hash_updated(email_source_paths, "last_email_source_files_hash", options.is_force):
145         run(["scripts/setup/inline-email-css"])
146     else:
147         print("No need to run `scripts/setup/inline-email-css`.")
148 
149     if not options.is_production_travis:
150         # The following block is skipped for the production Travis
151         # suite, because that suite doesn't make use of these elements
152         # of the development environment (it just uses the development
153         # environment to build a release tarball).
154 
155         # Need to set up Django before using template_database_status
156         os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zproject.settings")
157         import django
158         django.setup()
159 
160         from zerver.lib.test_fixtures import template_database_status, run_db_migrations, \
161             destroy_leaked_test_databases
162 
163         try:
164             from zerver.lib.queue import SimpleQueueClient
165             SimpleQueueClient()
166             rabbitmq_is_configured = True
167         except Exception:
168             rabbitmq_is_configured = False
169 
170         if options.is_force or not rabbitmq_is_configured:
171             run(["scripts/setup/configure-rabbitmq"])
172         else:
173             print("RabbitMQ is already configured.")
174 
175         migration_status_path = os.path.join(UUID_VAR_PATH, "migration_status_dev")
176         dev_template_db_status = template_database_status(
177             migration_status=migration_status_path,
178             settings="zproject.settings",
179             database_name="zulip",
180         )
181         if options.is_force or dev_template_db_status == 'needs_rebuild':
182             run(["tools/setup/postgres-init-dev-db"])
183             run(["tools/do-destroy-rebuild-database"])
184         elif dev_template_db_status == 'run_migrations':
185             run_db_migrations('dev')
186         elif dev_template_db_status == 'current':
187             print("No need to regenerate the dev DB.")
188 
189         test_template_db_status = template_database_status()
190         if options.is_force or test_template_db_status == 'needs_rebuild':
191             run(["tools/setup/postgres-init-test-db"])
192             run(["tools/do-destroy-rebuild-test-database"])
193         elif test_template_db_status == 'run_migrations':
194             run_db_migrations('test')
195         elif test_template_db_status == 'current':
196             print("No need to regenerate the test DB.")
197 
198         # Consider updating generated translations data: both `.mo`
199         # files and `language-options.json`.
200         paths = ['zerver/management/commands/compilemessages.py']
201         paths += glob.glob('locale/*/LC_MESSAGES/*.po')
202         paths += glob.glob('locale/*/translations.json')
203 
204         if file_or_package_hash_updated(paths, "last_compilemessages_hash", options.is_force):
205             run(["./manage.py", "compilemessages"])
206         else:
207             print("No need to run `manage.py compilemessages`.")
208 
209         destroyed = destroy_leaked_test_databases()
210         if destroyed:
211             print("Dropped %s stale test databases!" % (destroyed,))
212 
213     run(["scripts/lib/clean-unused-caches", "--threshold=6"])
214 
215     # Keeping this cache file around can cause eslint to throw
216     # random TypeErrors when new/updated dependencies are added
217     if os.path.isfile('.eslintcache'):
218         # Remove this block when
219         # https://github.com/eslint/eslint/issues/11639 is fixed
220         # upstream.
221         os.remove('.eslintcache')
222 
223     # Clean up the root of the `var/` directory for various
224     # testing-related files that we have migrated to
225     # `var/<uuid>/test-backend`.
226     print("Cleaning var/ directory files...")
227     var_paths = glob.glob('var/test*')
228     var_paths.append('var/bot_avatar')
229     for path in var_paths:
230         try:
231             if os.path.isdir(path):
232                 shutil.rmtree(path)
233             else:
234                 os.remove(path)
235         except FileNotFoundError:
236             pass
237 
238     version_file = os.path.join(UUID_VAR_PATH, 'provision_version')
239     print('writing to %s\n' % (version_file,))
240     open(version_file, 'w').write(PROVISION_VERSION + '\n')
241 
242     print()
243     print(OKBLUE + "Zulip development environment setup succeeded!" + ENDC)
244     return 0
245 
246 if __name__ == "__main__":
247     parser = argparse.ArgumentParser()
248     parser.add_argument('--force', action='store_true', dest='is_force',
249                         default=False,
250                         help="Ignore all provisioning optimizations.")
251 
252     parser.add_argument('--production-travis', action='store_true',
253                         dest='is_production_travis',
254                         default=False,
255                         help="Provision for Travis with production settings.")
256 
257     options = parser.parse_args()
258     sys.exit(main(options))
259
```
--- 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/tools/lib/provision_inner.py b/tools/lib/provision_inner.py
--- a/tools/lib/provision_inner.py
+++ b/tools/lib/provision_inner.py
@@ -172,12 +172,7 @@
         else:
             print("RabbitMQ is already configured.")
 
-        migration_status_path = os.path.join(UUID_VAR_PATH, "migration_status_dev")
-        dev_template_db_status = template_database_status(
-            migration_status=migration_status_path,
-            settings="zproject.settings",
-            database_name="zulip",
-        )
+        dev_template_db_status = template_database_status('dev')
         if options.is_force or dev_template_db_status == 'needs_rebuild':
             run(["tools/setup/postgres-init-dev-db"])
             run(["tools/do-destroy-rebuild-database"])
@@ -186,7 +181,7 @@
         elif dev_template_db_status == 'current':
             print("No need to regenerate the dev DB.")
 
-        test_template_db_status = template_database_status()
+        test_template_db_status = template_database_status('test')
         if options.is_force or test_template_db_status == 'needs_rebuild':
             run(["tools/setup/postgres-init-test-db"])
             run(["tools/do-destroy-rebuild-test-database"])

{"golden_diff": "diff --git a/tools/lib/provision_inner.py b/tools/lib/provision_inner.py\n--- a/tools/lib/provision_inner.py\n+++ b/tools/lib/provision_inner.py\n@@ -172,12 +172,7 @@\n         else:\n             print(\"RabbitMQ is already configured.\")\n \n-        migration_status_path = os.path.join(UUID_VAR_PATH, \"migration_status_dev\")\n-        dev_template_db_status = template_database_status(\n-            migration_status=migration_status_path,\n-            settings=\"zproject.settings\",\n-            database_name=\"zulip\",\n-        )\n+        dev_template_db_status = template_database_status('dev')\n         if options.is_force or dev_template_db_status == 'needs_rebuild':\n             run([\"tools/setup/postgres-init-dev-db\"])\n             run([\"tools/do-destroy-rebuild-database\"])\n@@ -186,7 +181,7 @@\n         elif dev_template_db_status == 'current':\n             print(\"No need to regenerate the dev DB.\")\n \n-        test_template_db_status = template_database_status()\n+        test_template_db_status = template_database_status('test')\n         if options.is_force or test_template_db_status == 'needs_rebuild':\n             run([\"tools/setup/postgres-init-test-db\"])\n             run([\"tools/do-destroy-rebuild-test-database\"])\n", "issue": "provision: Clean up interface for template_database_status\nFollowing 84edb5c5162e9299ab5fb6a0a59c402484caa98c, it's clear that we should have a cleaner database for how the arguments to `template_database_status` are passed to correctly check whether the target database (whether zulip_test_template, used by `test-backend`, or the ).  I think we could do significantly better by defining a class or TypedDict defining the settings for the `zulip_test_template` and `zulip` databases and accessing those. (Or maybe just having there be a single argument for which database we're checking?).  \r\n\r\nFundamentally, there's only two valid ways to call `template_database_status`, so it shouldn't take like 5 arguments with defaults, it should take one argument that specifies which database we want to access.\n", "before_files": [{"content": "#!/usr/bin/env python3\nimport os\nimport sys\nimport argparse\nimport glob\nimport shutil\n\nZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n\nsys.path.append(ZULIP_PATH)\nfrom scripts.lib.zulip_tools import run, run_as_root, OKBLUE, ENDC, \\\n    get_dev_uuid_var_path, file_or_package_hash_updated\n\nfrom version import PROVISION_VERSION\n\nfrom tools.setup.generate_zulip_bots_static_files import generate_zulip_bots_static_files\n\nVENV_PATH = \"/srv/zulip-py3-venv\"\nVAR_DIR_PATH = os.path.join(ZULIP_PATH, 'var')\nLOG_DIR_PATH = os.path.join(VAR_DIR_PATH, 'log')\nUPLOAD_DIR_PATH = os.path.join(VAR_DIR_PATH, 'uploads')\nTEST_UPLOAD_DIR_PATH = os.path.join(VAR_DIR_PATH, 'test_uploads')\nCOVERAGE_DIR_PATH = os.path.join(VAR_DIR_PATH, 'coverage')\nNODE_TEST_COVERAGE_DIR_PATH = os.path.join(VAR_DIR_PATH, 'node-coverage')\nXUNIT_XML_TEST_RESULTS_DIR_PATH = os.path.join(VAR_DIR_PATH, 'xunit-test-results')\n\nis_travis = 'TRAVIS' in os.environ\n\n# TODO: De-duplicate this with emoji_dump.py\nEMOJI_CACHE_PATH = \"/srv/zulip-emoji-cache\"\nif is_travis:\n    # In Travis CI, we don't have root access\n    EMOJI_CACHE_PATH = \"/home/travis/zulip-emoji-cache\"\n\nUUID_VAR_PATH = get_dev_uuid_var_path()\n\ndef setup_shell_profile(shell_profile):\n    # type: (str) -> None\n    shell_profile_path = os.path.expanduser(shell_profile)\n\n    def write_command(command):\n        # type: (str) -> None\n        if os.path.exists(shell_profile_path):\n            with open(shell_profile_path, 'r') as shell_profile_file:\n                lines = [line.strip() for line in shell_profile_file.readlines()]\n            if command not in lines:\n                with open(shell_profile_path, 'a+') as shell_profile_file:\n                    shell_profile_file.writelines(command + '\\n')\n        else:\n            with open(shell_profile_path, 'w') as shell_profile_file:\n                shell_profile_file.writelines(command + '\\n')\n\n    source_activate_command = \"source \" + os.path.join(VENV_PATH, \"bin\", \"activate\")\n    write_command(source_activate_command)\n    if os.path.exists('/srv/zulip'):\n        write_command('cd /srv/zulip')\n\ndef setup_bash_profile() -> None:\n    \"\"\"Select a bash profile file to add setup code to.\"\"\"\n\n    BASH_PROFILES = [\n        os.path.expanduser(p) for p in\n        (\"~/.bash_profile\", \"~/.bash_login\", \"~/.profile\")\n    ]\n\n    def clear_old_profile() -> None:\n        # An earlier version of this script would output a fresh .bash_profile\n        # even though a .profile existed in the image used. As a convenience to\n        # existing developers (and, perhaps, future developers git-bisecting the\n        # provisioning scripts), check for this situation, and blow away the\n        # created .bash_profile if one is found.\n\n        BASH_PROFILE = BASH_PROFILES[0]\n        DOT_PROFILE = BASH_PROFILES[2]\n        OLD_PROFILE_TEXT = \"source /srv/zulip-py3-venv/bin/activate\\n\" + \\\n            \"cd /srv/zulip\\n\"\n\n        if os.path.exists(DOT_PROFILE):\n            try:\n                with open(BASH_PROFILE, \"r\") as f:\n                    profile_contents = f.read()\n                if profile_contents == OLD_PROFILE_TEXT:\n                    os.unlink(BASH_PROFILE)\n            except FileNotFoundError:\n                pass\n\n    clear_old_profile()\n\n    for candidate_profile in BASH_PROFILES:\n        if os.path.exists(candidate_profile):\n            setup_shell_profile(candidate_profile)\n            break\n    else:\n        # no existing bash profile found; claim .bash_profile\n        setup_shell_profile(BASH_PROFILES[0])\n\ndef main(options: argparse.Namespace) -> int:\n    setup_bash_profile()\n    setup_shell_profile('~/.zprofile')\n\n    # This needs to happen before anything that imports zproject.settings.\n    run([\"scripts/setup/generate_secrets.py\", \"--development\"])\n\n    # create log directory `zulip/var/log`\n    os.makedirs(LOG_DIR_PATH, exist_ok=True)\n    # create upload directory `var/uploads`\n    os.makedirs(UPLOAD_DIR_PATH, exist_ok=True)\n    # create test upload directory `var/test_upload`\n    os.makedirs(TEST_UPLOAD_DIR_PATH, exist_ok=True)\n    # create coverage directory `var/coverage`\n    os.makedirs(COVERAGE_DIR_PATH, exist_ok=True)\n    # create linecoverage directory `var/node-coverage`\n    os.makedirs(NODE_TEST_COVERAGE_DIR_PATH, exist_ok=True)\n    # create XUnit XML test results directory`var/xunit-test-results`\n    os.makedirs(XUNIT_XML_TEST_RESULTS_DIR_PATH, exist_ok=True)\n\n    # The `build_emoji` script requires `emoji-datasource` package\n    # which we install via npm; thus this step is after installing npm\n    # packages.\n    if not os.access(EMOJI_CACHE_PATH, os.W_OK):\n        run_as_root([\"mkdir\", \"-p\", EMOJI_CACHE_PATH])\n        run_as_root([\"chown\", \"%s:%s\" % (os.getuid(), os.getgid()), EMOJI_CACHE_PATH])\n    run([\"tools/setup/emoji/build_emoji\"])\n\n    # copy over static files from the zulip_bots package\n    generate_zulip_bots_static_files()\n\n    build_pygments_data_paths = [\"tools/setup/build_pygments_data\", \"tools/setup/lang.json\"]\n    from pygments import __version__ as pygments_version\n    if file_or_package_hash_updated(build_pygments_data_paths, \"build_pygments_data_hash\", options.is_force,\n                                    [pygments_version]):\n        run([\"tools/setup/build_pygments_data\"])\n    else:\n        print(\"No need to run `tools/setup/build_pygments_data`.\")\n\n    update_authors_json_paths = [\"tools/update-authors-json\", \"zerver/tests/fixtures/authors.json\"]\n    if file_or_package_hash_updated(update_authors_json_paths, \"update_authors_json_hash\", options.is_force):\n        run([\"tools/update-authors-json\", \"--use-fixture\"])\n    else:\n        print(\"No need to run `tools/update-authors-json`.\")\n\n    email_source_paths = [\"scripts/setup/inline-email-css\", \"templates/zerver/emails/email.css\"]\n    email_source_paths += glob.glob('templates/zerver/emails/*.source.html')\n    if file_or_package_hash_updated(email_source_paths, \"last_email_source_files_hash\", options.is_force):\n        run([\"scripts/setup/inline-email-css\"])\n    else:\n        print(\"No need to run `scripts/setup/inline-email-css`.\")\n\n    if not options.is_production_travis:\n        # The following block is skipped for the production Travis\n        # suite, because that suite doesn't make use of these elements\n        # of the development environment (it just uses the development\n        # environment to build a release tarball).\n\n        # Need to set up Django before using template_database_status\n        os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"zproject.settings\")\n        import django\n        django.setup()\n\n        from zerver.lib.test_fixtures import template_database_status, run_db_migrations, \\\n            destroy_leaked_test_databases\n\n        try:\n            from zerver.lib.queue import SimpleQueueClient\n            SimpleQueueClient()\n            rabbitmq_is_configured = True\n        except Exception:\n            rabbitmq_is_configured = False\n\n        if options.is_force or not rabbitmq_is_configured:\n            run([\"scripts/setup/configure-rabbitmq\"])\n        else:\n            print(\"RabbitMQ is already configured.\")\n\n        migration_status_path = os.path.join(UUID_VAR_PATH, \"migration_status_dev\")\n        dev_template_db_status = template_database_status(\n            migration_status=migration_status_path,\n            settings=\"zproject.settings\",\n            database_name=\"zulip\",\n        )\n        if options.is_force or dev_template_db_status == 'needs_rebuild':\n            run([\"tools/setup/postgres-init-dev-db\"])\n            run([\"tools/do-destroy-rebuild-database\"])\n        elif dev_template_db_status == 'run_migrations':\n            run_db_migrations('dev')\n        elif dev_template_db_status == 'current':\n            print(\"No need to regenerate the dev DB.\")\n\n        test_template_db_status = template_database_status()\n        if options.is_force or test_template_db_status == 'needs_rebuild':\n            run([\"tools/setup/postgres-init-test-db\"])\n            run([\"tools/do-destroy-rebuild-test-database\"])\n        elif test_template_db_status == 'run_migrations':\n            run_db_migrations('test')\n        elif test_template_db_status == 'current':\n            print(\"No need to regenerate the test DB.\")\n\n        # Consider updating generated translations data: both `.mo`\n        # files and `language-options.json`.\n        paths = ['zerver/management/commands/compilemessages.py']\n        paths += glob.glob('locale/*/LC_MESSAGES/*.po')\n        paths += glob.glob('locale/*/translations.json')\n\n        if file_or_package_hash_updated(paths, \"last_compilemessages_hash\", options.is_force):\n            run([\"./manage.py\", \"compilemessages\"])\n        else:\n            print(\"No need to run `manage.py compilemessages`.\")\n\n        destroyed = destroy_leaked_test_databases()\n        if destroyed:\n            print(\"Dropped %s stale test databases!\" % (destroyed,))\n\n    run([\"scripts/lib/clean-unused-caches\", \"--threshold=6\"])\n\n    # Keeping this cache file around can cause eslint to throw\n    # random TypeErrors when new/updated dependencies are added\n    if os.path.isfile('.eslintcache'):\n        # Remove this block when\n        # https://github.com/eslint/eslint/issues/11639 is fixed\n        # upstream.\n        os.remove('.eslintcache')\n\n    # Clean up the root of the `var/` directory for various\n    # testing-related files that we have migrated to\n    # `var/<uuid>/test-backend`.\n    print(\"Cleaning var/ directory files...\")\n    var_paths = glob.glob('var/test*')\n    var_paths.append('var/bot_avatar')\n    for path in var_paths:\n        try:\n            if os.path.isdir(path):\n                shutil.rmtree(path)\n            else:\n                os.remove(path)\n        except FileNotFoundError:\n            pass\n\n    version_file = os.path.join(UUID_VAR_PATH, 'provision_version')\n    print('writing to %s\\n' % (version_file,))\n    open(version_file, 'w').write(PROVISION_VERSION + '\\n')\n\n    print()\n    print(OKBLUE + \"Zulip development environment setup succeeded!\" + ENDC)\n    return 0\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument('--force', action='store_true', dest='is_force',\n                        default=False,\n                        help=\"Ignore all provisioning optimizations.\")\n\n    parser.add_argument('--production-travis', action='store_true',\n                        dest='is_production_travis',\n                        default=False,\n                        help=\"Provision for Travis with production settings.\")\n\n    options = parser.parse_args()\n    sys.exit(main(options))\n", "path": "tools/lib/provision_inner.py"}], "after_files": [{"content": "#!/usr/bin/env python3\nimport os\nimport sys\nimport argparse\nimport glob\nimport shutil\n\nZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))\n\nsys.path.append(ZULIP_PATH)\nfrom scripts.lib.zulip_tools import run, run_as_root, OKBLUE, ENDC, \\\n    get_dev_uuid_var_path, file_or_package_hash_updated\n\nfrom version import PROVISION_VERSION\n\nfrom tools.setup.generate_zulip_bots_static_files import generate_zulip_bots_static_files\n\nVENV_PATH = \"/srv/zulip-py3-venv\"\nVAR_DIR_PATH = os.path.join(ZULIP_PATH, 'var')\nLOG_DIR_PATH = os.path.join(VAR_DIR_PATH, 'log')\nUPLOAD_DIR_PATH = os.path.join(VAR_DIR_PATH, 'uploads')\nTEST_UPLOAD_DIR_PATH = os.path.join(VAR_DIR_PATH, 'test_uploads')\nCOVERAGE_DIR_PATH = os.path.join(VAR_DIR_PATH, 'coverage')\nNODE_TEST_COVERAGE_DIR_PATH = os.path.join(VAR_DIR_PATH, 'node-coverage')\nXUNIT_XML_TEST_RESULTS_DIR_PATH = os.path.join(VAR_DIR_PATH, 'xunit-test-results')\n\nis_travis = 'TRAVIS' in os.environ\n\n# TODO: De-duplicate this with emoji_dump.py\nEMOJI_CACHE_PATH = \"/srv/zulip-emoji-cache\"\nif is_travis:\n    # In Travis CI, we don't have root access\n    EMOJI_CACHE_PATH = \"/home/travis/zulip-emoji-cache\"\n\nUUID_VAR_PATH = get_dev_uuid_var_path()\n\ndef setup_shell_profile(shell_profile):\n    # type: (str) -> None\n    shell_profile_path = os.path.expanduser(shell_profile)\n\n    def write_command(command):\n        # type: (str) -> None\n        if os.path.exists(shell_profile_path):\n            with open(shell_profile_path, 'r') as shell_profile_file:\n                lines = [line.strip() for line in shell_profile_file.readlines()]\n            if command not in lines:\n                with open(shell_profile_path, 'a+') as shell_profile_file:\n                    shell_profile_file.writelines(command + '\\n')\n        else:\n            with open(shell_profile_path, 'w') as shell_profile_file:\n                shell_profile_file.writelines(command + '\\n')\n\n    source_activate_command = \"source \" + os.path.join(VENV_PATH, \"bin\", \"activate\")\n    write_command(source_activate_command)\n    if os.path.exists('/srv/zulip'):\n        write_command('cd /srv/zulip')\n\ndef setup_bash_profile() -> None:\n    \"\"\"Select a bash profile file to add setup code to.\"\"\"\n\n    BASH_PROFILES = [\n        os.path.expanduser(p) for p in\n        (\"~/.bash_profile\", \"~/.bash_login\", \"~/.profile\")\n    ]\n\n    def clear_old_profile() -> None:\n        # An earlier version of this script would output a fresh .bash_profile\n        # even though a .profile existed in the image used. As a convenience to\n        # existing developers (and, perhaps, future developers git-bisecting the\n        # provisioning scripts), check for this situation, and blow away the\n        # created .bash_profile if one is found.\n\n        BASH_PROFILE = BASH_PROFILES[0]\n        DOT_PROFILE = BASH_PROFILES[2]\n        OLD_PROFILE_TEXT = \"source /srv/zulip-py3-venv/bin/activate\\n\" + \\\n            \"cd /srv/zulip\\n\"\n\n        if os.path.exists(DOT_PROFILE):\n            try:\n                with open(BASH_PROFILE, \"r\") as f:\n                    profile_contents = f.read()\n                if profile_contents == OLD_PROFILE_TEXT:\n                    os.unlink(BASH_PROFILE)\n            except FileNotFoundError:\n                pass\n\n    clear_old_profile()\n\n    for candidate_profile in BASH_PROFILES:\n        if os.path.exists(candidate_profile):\n            setup_shell_profile(candidate_profile)\n            break\n    else:\n        # no existing bash profile found; claim .bash_profile\n        setup_shell_profile(BASH_PROFILES[0])\n\ndef main(options: argparse.Namespace) -> int:\n    setup_bash_profile()\n    setup_shell_profile('~/.zprofile')\n\n    # This needs to happen before anything that imports zproject.settings.\n    run([\"scripts/setup/generate_secrets.py\", \"--development\"])\n\n    # create log directory `zulip/var/log`\n    os.makedirs(LOG_DIR_PATH, exist_ok=True)\n    # create upload directory `var/uploads`\n    os.makedirs(UPLOAD_DIR_PATH, exist_ok=True)\n    # create test upload directory `var/test_upload`\n    os.makedirs(TEST_UPLOAD_DIR_PATH, exist_ok=True)\n    # create coverage directory `var/coverage`\n    os.makedirs(COVERAGE_DIR_PATH, exist_ok=True)\n    # create linecoverage directory `var/node-coverage`\n    os.makedirs(NODE_TEST_COVERAGE_DIR_PATH, exist_ok=True)\n    # create XUnit XML test results directory`var/xunit-test-results`\n    os.makedirs(XUNIT_XML_TEST_RESULTS_DIR_PATH, exist_ok=True)\n\n    # The `build_emoji` script requires `emoji-datasource` package\n    # which we install via npm; thus this step is after installing npm\n    # packages.\n    if not os.access(EMOJI_CACHE_PATH, os.W_OK):\n        run_as_root([\"mkdir\", \"-p\", EMOJI_CACHE_PATH])\n        run_as_root([\"chown\", \"%s:%s\" % (os.getuid(), os.getgid()), EMOJI_CACHE_PATH])\n    run([\"tools/setup/emoji/build_emoji\"])\n\n    # copy over static files from the zulip_bots package\n    generate_zulip_bots_static_files()\n\n    build_pygments_data_paths = [\"tools/setup/build_pygments_data\", \"tools/setup/lang.json\"]\n    from pygments import __version__ as pygments_version\n    if file_or_package_hash_updated(build_pygments_data_paths, \"build_pygments_data_hash\", options.is_force,\n                                    [pygments_version]):\n        run([\"tools/setup/build_pygments_data\"])\n    else:\n        print(\"No need to run `tools/setup/build_pygments_data`.\")\n\n    update_authors_json_paths = [\"tools/update-authors-json\", \"zerver/tests/fixtures/authors.json\"]\n    if file_or_package_hash_updated(update_authors_json_paths, \"update_authors_json_hash\", options.is_force):\n        run([\"tools/update-authors-json\", \"--use-fixture\"])\n    else:\n        print(\"No need to run `tools/update-authors-json`.\")\n\n    email_source_paths = [\"scripts/setup/inline-email-css\", \"templates/zerver/emails/email.css\"]\n    email_source_paths += glob.glob('templates/zerver/emails/*.source.html')\n    if file_or_package_hash_updated(email_source_paths, \"last_email_source_files_hash\", options.is_force):\n        run([\"scripts/setup/inline-email-css\"])\n    else:\n        print(\"No need to run `scripts/setup/inline-email-css`.\")\n\n    if not options.is_production_travis:\n        # The following block is skipped for the production Travis\n        # suite, because that suite doesn't make use of these elements\n        # of the development environment (it just uses the development\n        # environment to build a release tarball).\n\n        # Need to set up Django before using template_database_status\n        os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"zproject.settings\")\n        import django\n        django.setup()\n\n        from zerver.lib.test_fixtures import template_database_status, run_db_migrations, \\\n            destroy_leaked_test_databases\n\n        try:\n            from zerver.lib.queue import SimpleQueueClient\n            SimpleQueueClient()\n            rabbitmq_is_configured = True\n        except Exception:\n            rabbitmq_is_configured = False\n\n        if options.is_force or not rabbitmq_is_configured:\n            run([\"scripts/setup/configure-rabbitmq\"])\n        else:\n            print(\"RabbitMQ is already configured.\")\n\n        dev_template_db_status = template_database_status('dev')\n        if options.is_force or dev_template_db_status == 'needs_rebuild':\n            run([\"tools/setup/postgres-init-dev-db\"])\n            run([\"tools/do-destroy-rebuild-database\"])\n        elif dev_template_db_status == 'run_migrations':\n            run_db_migrations('dev')\n        elif dev_template_db_status == 'current':\n            print(\"No need to regenerate the dev DB.\")\n\n        test_template_db_status = template_database_status('test')\n        if options.is_force or test_template_db_status == 'needs_rebuild':\n            run([\"tools/setup/postgres-init-test-db\"])\n            run([\"tools/do-destroy-rebuild-test-database\"])\n        elif test_template_db_status == 'run_migrations':\n            run_db_migrations('test')\n        elif test_template_db_status == 'current':\n            print(\"No need to regenerate the test DB.\")\n\n        # Consider updating generated translations data: both `.mo`\n        # files and `language-options.json`.\n        paths = ['zerver/management/commands/compilemessages.py']\n        paths += glob.glob('locale/*/LC_MESSAGES/*.po')\n        paths += glob.glob('locale/*/translations.json')\n\n        if file_or_package_hash_updated(paths, \"last_compilemessages_hash\", options.is_force):\n            run([\"./manage.py\", \"compilemessages\"])\n        else:\n            print(\"No need to run `manage.py compilemessages`.\")\n\n        destroyed = destroy_leaked_test_databases()\n        if destroyed:\n            print(\"Dropped %s stale test databases!\" % (destroyed,))\n\n    run([\"scripts/lib/clean-unused-caches\", \"--threshold=6\"])\n\n    # Keeping this cache file around can cause eslint to throw\n    # random TypeErrors when new/updated dependencies are added\n    if os.path.isfile('.eslintcache'):\n        # Remove this block when\n        # https://github.com/eslint/eslint/issues/11639 is fixed\n        # upstream.\n        os.remove('.eslintcache')\n\n    # Clean up the root of the `var/` directory for various\n    # testing-related files that we have migrated to\n    # `var/<uuid>/test-backend`.\n    print(\"Cleaning var/ directory files...\")\n    var_paths = glob.glob('var/test*')\n    var_paths.append('var/bot_avatar')\n    for path in var_paths:\n        try:\n            if os.path.isdir(path):\n                shutil.rmtree(path)\n            else:\n                os.remove(path)\n        except FileNotFoundError:\n            pass\n\n    version_file = os.path.join(UUID_VAR_PATH, 'provision_version')\n    print('writing to %s\\n' % (version_file,))\n    open(version_file, 'w').write(PROVISION_VERSION + '\\n')\n\n    print()\n    print(OKBLUE + \"Zulip development environment setup succeeded!\" + ENDC)\n    return 0\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument('--force', action='store_true', dest='is_force',\n                        default=False,\n                        help=\"Ignore all provisioning optimizations.\")\n\n    parser.add_argument('--production-travis', action='store_true',\n                        dest='is_production_travis',\n                        default=False,\n                        help=\"Provision for Travis with production settings.\")\n\n    options = parser.parse_args()\n    sys.exit(main(options))\n", "path": "tools/lib/provision_inner.py"}]}