Repository: acl-org/acl-anthology

Issue:
Correction to Anthology ID 2020.acl-main.178
**Please be sure to add the Anthology ID in the title**

[See here](https://www.aclweb.org/anthology/info/corrections/) to read about the three types of corrections.

## Metadata correction: please describe the issue here**
The second author's last name on paper `2020.acl-main.178` starts with a lowercase letter (Eric horvitz), causing a problem in author linking, and creating duplicate author pages: https://www.aclweb.org/anthology/people/e/eric-horvitz/ and https://www.aclweb.org/anthology/people/e/eric-horvitz1/. The correct author name is [Eric Horvitz](https://www.aclweb.org/anthology/people/e/eric-horvitz/). Any way to correct this?


Discussion:

Resolving patch:
diff --git a/bin/add_revision.py b/bin/add_revision.py
--- a/bin/add_revision.py
+++ b/bin/add_revision.py
@@ -48,12 +48,43 @@
     make_simple_element,
     indent,
     compute_hash,
+    infer_url,
+    is_newstyle_id,
 )
 from anthology.data import ANTHOLOGY_PDF
 
 import lxml.etree as ET
 import urllib.request
 
+from datetime import datetime
+
+
+def validate_file_type(path):
+    """Ensure downloaded file mime type matches its extension (e.g., PDF)"""
+    detected = filetype.guess(path)
+    if detected is None or not detected.mime.endswith(detected.extension):
+        mime_type = 'UNKNOWN' if detected is None else detected.mime
+        print(
+            f"FATAL: {args.anthology_id} file {path} has MIME type {mime_type}",
+            file=sys.stderr,
+        )
+        sys.exit(1)
+
+
+def download_file(source, dest):
+    try:
+        print(
+            f"-> Downloading file from {source} to {dest}", file=sys.stderr,
+        )
+        with urllib.request.urlopen(source) as url, open(dest, mode="wb") as fh:
+            fh.write(url.read())
+    except ssl.SSLError:
+        print(
+            f"-> FATAL: An SSL error was encountered in downloading {source}.",
+            file=sys.stderr,
+        )
+        sys.exit(1)
+
 
 def main(args):
     def maybe_copy(file_from, file_to):
@@ -75,30 +106,14 @@ def maybe_copy(file_from, file_to):
     # TODO: make sure path exists, or download URL to temp file
     if args.path.startswith("http"):
         _, input_file_path = tempfile.mkstemp()
-        try:
-            print(f"-> Downloading file from {args.path}", file=sys.stderr)
-            with urllib.request.urlopen(args.path) as url, open(
-                input_file_path, mode="wb"
-            ) as input_file_fh:
-                input_file_fh.write(url.read())
-        except ssl.SSLError:
-            print(
-                "An SSL error was encountered in downloading the files.", file=sys.stderr
-            )
-            sys.exit(1)
+        download_file(args.path, input_file_path)
     else:
         input_file_path = args.path
 
-    detected = filetype.guess(input_file_path)
-    if detected is None or not detected.mime.endswith(detected.extension):
-        mime_type = 'UNKNOWN' if detected is None else detected.mime
-        print(
-            f"FATAL: {args.anthology_id} file {args.path} has MIME type {mime_type}",
-            file=sys.stderr,
-        )
-        sys.exit(1)
+    validate_file_type(input_file_path)
 
     collection_id, volume_id, paper_id = deconstruct_anthology_id(args.anthology_id)
+    venue_name = collection_id.split(".")[1]
     paper_extension = args.path.split(".")[-1]
 
     # The new version
@@ -107,6 +122,22 @@ def maybe_copy(file_from, file_to):
     with open(input_file_path, "rb") as f:
         checksum = compute_hash(f.read())
 
+    # Files for old-style IDs are stored under anthology-files/pdf/P/P19/*
+    # Files for new-style IDs are stored under anthology-files/pdf/2020.acl/*
+    if is_newstyle_id(args.anthology_id):
+        output_dir = os.path.join(args.anthology_dir, "pdf", venue_name)
+    else:
+        output_dir = os.path.join(
+            args.anthology_dir, "pdf", collection_id[0], collection_id
+        )
+
+    # Make sure directory exists
+    if not os.path.exists(output_dir):
+        print(f"-> Creating directory {output_dir}", file=sys.stderr)
+        os.makedirs(output_dir)
+
+    canonical_path = os.path.join(output_dir, f"{args.anthology_id}.pdf")
+
     # Update XML
     xml_file = os.path.join(
         os.path.dirname(sys.argv[0]), "..", "data", "xml", f"{collection_id}.xml"
@@ -120,7 +151,28 @@ def maybe_copy(file_from, file_to):
             revno = int(revision.attrib["id"]) + 1
 
         if not args.dry_run:
+            # Update the URL hash on the <url> tag
+            url = paper.find("./url")
+            if url is not None:
+                url.attrib["hash"] = checksum
+
             if not args.erratum and revno == 2:
+                if paper.find("./url") is not None:
+                    current_version_url = infer_url(paper.find("./url").text) + ".pdf"
+
+                # Download original file
+                # There are no versioned files the first time around, so create the first one
+                # (essentially backing up the original version)
+                revised_file_v1_path = os.path.join(
+                    output_dir, f"{args.anthology_id}{change_letter}1.pdf"
+                )
+
+                download_file(current_version_url, revised_file_v1_path)
+                validate_file_type(revised_file_v1_path)
+
+                with open(revised_file_v1_path, "rb") as f:
+                    old_checksum = compute_hash(f.read())
+
                 # First revision requires making the original version explicit
                 revision = make_simple_element(
                     change_type,
@@ -128,7 +180,7 @@ def maybe_copy(file_from, file_to):
                     attrib={
                         "id": "1",
                         "href": f"{args.anthology_id}{change_letter}1",
-                        "hash": checksum,
+                        "hash": old_checksum,
                     },
                     parent=paper,
                 )
@@ -158,45 +210,6 @@ def maybe_copy(file_from, file_to):
         )
         sys.exit(1)
 
-    output_dir = os.path.join(args.anthology_dir, "pdf", collection_id[0], collection_id)
-
-    # Make sure directory exists
-    if not os.path.exists(output_dir):
-        print(f"-> Creating directory {output_dir}", file=sys.stderr)
-        os.makedirs(output_dir)
-
-    canonical_path = os.path.join(output_dir, f"{args.anthology_id}.pdf")
-
-    if not args.erratum and revno == 2:
-        # There are no versioned files the first time around, so create the first one
-        # (essentially backing up the original version)
-        revised_file_v1_path = os.path.join(
-            output_dir, f"{args.anthology_id}{change_letter}1.pdf"
-        )
-
-        current_version = ANTHOLOGY_PDF.format(args.anthology_id)
-        if not args.dry_run:
-            try:
-                print(
-                    f"-> Downloading file from {args.path} to {revised_file_v1_path}",
-                    file=sys.stderr,
-                )
-                with urllib.request.urlopen(current_version) as url, open(
-                    revised_file_v1_path, mode="wb"
-                ) as fh:
-                    fh.write(url.read())
-            except ssl.SSLError:
-                print(
-                    f"-> FATAL: An SSL error was encountered in downloading {args.path}.",
-                    file=sys.stderr,
-                )
-                sys.exit(1)
-        else:
-            print(
-                f"-> DRY RUN: Downlading file from {args.path} to {revised_file_v1_path}",
-                file=sys.stderr,
-            )
-
     revised_file_versioned_path = os.path.join(
         output_dir, f"{args.anthology_id}{change_letter}{revno}.pdf"
     )
@@ -227,8 +240,14 @@ def maybe_copy(file_from, file_to):
         action="store_true",
         help="This is an erratum instead of a revision.",
     )
+    now = datetime.now()
+    today = f"{now.year}-{now.month:02d}-{now.day:02d}"
     parser.add_argument(
-        "--date", "-d", type=str, help="The date of the revision (ISO 8601 format)"
+        "--date",
+        "-d",
+        type=str,
+        default=today,
+        help="The date of the revision (ISO 8601 format)",
     )
     parser.add_argument(
         "--dry-run", "-n", action="store_true", default=False, help="Just a dry run."


Test patch: