crowdin: Add unzipping

* We can trigger a build on crowdin and download the zip manually
* Add an option to be able to use the zips and treat it as if we called
  crowdin download

Change-Id: I756368014b01176d18f186dfbc931114e662ed78
diff --git a/crowdin_sync.py b/crowdin_sync.py
index add45a7..66f4893 100755
--- a/crowdin_sync.py
+++ b/crowdin_sync.py
@@ -27,6 +27,7 @@
 from signal import signal, SIGINT
 
 import download
+import from_zip
 import gerrit
 import upload
 import utils
@@ -72,6 +73,9 @@
         help="Path to crowdin executable (will look in PATH by default)",
         default="crowdin",
     )
+    parser.add_argument(
+        "--unzip", nargs="+", help="Specify a translation zip to treat like a download"
+    )
     return parser.parse_args()
 
 
@@ -121,6 +125,9 @@
             config_dict,
             args.path_to_crowdin,
         )
+    elif args.unzip:
+        xml_files = utils.get_xml_files(base_path, default_branch)
+        from_zip.unzip(args.unzip, base_path, default_branch, xml_files, username)
 
     if download.has_created_commits() or upload.has_uploaded():
         print("\nDone!")
diff --git a/from_zip.py b/from_zip.py
new file mode 100644
index 0000000..2152c4f
--- /dev/null
+++ b/from_zip.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# from_zip.py
+#
+# Helper script for extracting translations from one or more zips and
+# uploading them to LineageOS' gerrit
+#
+# Copyright (C) 2022 The LineageOS Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import zipfile
+
+from pathlib import Path
+
+import download
+
+
+def unzip(zip_files, base_path, branch, xml, username):
+    print("\nUnzipping files")
+    extracted = []
+    number = 1
+
+    for zip_file in zip_files:
+        if not zipfile.is_zipfile(zip_file):
+            print(
+                f"WARNING: Specified file is not a valid zip file, skipping '{zip_file}'"
+            )
+            continue
+
+        print(f"File {number}/{len(zip_files)}")
+        with zipfile.ZipFile(zip_file, "r") as my_zip:
+            for zip_info in my_zip.infolist():
+                filename = zip_info.filename
+                if filename.startswith(branch) and filename.endswith(".xml"):
+                    p = Path(filename)
+                    # get rid of the parent folder
+                    filename = os.path.join(*list(p.parts[1:]))
+                    zip_info.filename = filename
+                    if filename not in extracted:
+                        extracted.append(filename)
+                    my_zip.extract(zip_info, path=base_path)
+        number += 1
+
+    if len(extracted) > 0:
+        download.upload_translations_gerrit(extracted, xml, base_path, branch, username)
+    else:
+        print("Nothing extracted or no new files found!")
diff --git a/utils.py b/utils.py
index 760f74e..cc32177 100644
--- a/utils.py
+++ b/utils.py
@@ -99,7 +99,7 @@
 
 def get_username(args):
     username = args.username
-    if (args.gerrit or args.download) and username is None:
+    if (args.gerrit or args.download or args.unzip) and username is None:
         # try getting the username from git
         msg, code = run_subprocess(
             ["git", "config", "--get", "review.review.lineageos.org.username"],