[git-cl] Add option to git-cl upload to prohibit changeid manipulation.

I recently encountered an error where I forgot to add a changeid locally to
some-but-not-all commits in a stack of commits. When attempting to upload
these commits via `git cl upload --no-squash`, I received a confusing message
instructing me to install the Gerrit commit-msg hook even after the hook was
installed. In order to debug this problem locally, I added the ability to
prevent `git cl upload ...` from attempting to change the contents of
messages. If the --no-add-changeid flag is passed, then the command will
simply fail quasi-informatively.

BUG=None
TEST=attempted to upload this CL via `git cl upload --no-squash --no-add-changeid`, confirm that it fails.

Change-Id: Id5f721c18143448db801095946f490880bb61786
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2828775
Reviewed-by: Dirk Pranke <dpranke@google.com>
Commit-Queue: Gregory Nisbet <gregorynisbet@google.com>
diff --git a/git_cl.py b/git_cl.py
index 1b441c0..5482382 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -2304,17 +2304,26 @@
         ref_to_push = RunGit(
             ['commit-tree', tree, '-p', parent, '-F', desc_tempfile]).strip()
     else:  # if not options.squash
-      if not git_footers.get_footer_change_id(change_desc.description):
-        DownloadGerritHook(False)
-        change_desc.set_description(
-            self._AddChangeIdToCommitMessage(
-                change_desc.description, git_diff_args))
+      if options.no_add_changeid:
+        pass
+      else:  # adding Change-Ids is okay.
+        if not git_footers.get_footer_change_id(change_desc.description):
+          DownloadGerritHook(False)
+          change_desc.set_description(
+              self._AddChangeIdToCommitMessage(change_desc.description,
+                                               git_diff_args))
       ref_to_push = 'HEAD'
       # For no-squash mode, we assume the remote called "origin" is the one we
       # want. It is not worthwhile to support different workflows for
       # no-squash mode.
       parent = 'origin/%s' % branch
-      change_id = git_footers.get_footer_change_id(change_desc.description)[0]
+      # attempt to extract the changeid from the current description
+      # fail informatively if not possible.
+      change_id_candidates = git_footers.get_footer_change_id(
+          change_desc.description)
+      if not change_id_candidates:
+        DieWithError("Unable to extract change-id from message.")
+      change_id = change_id_candidates[0]
 
     SaveDescriptionBackup(change_desc)
     commits = RunGitSilent(['rev-list', '%s..%s' % (parent,
@@ -4217,6 +4226,10 @@
                     help='Transmit the given string to the server when '
                     'performing git push (pass-through). See git-push '
                     'documentation for more details.')
+  parser.add_option('--no-add-changeid',
+                    action='store_true',
+                    dest='no_add_changeid',
+                    help='Do not add change-ids to messages.')
 
   orig_args = args
   (options, args) = parser.parse_args(args)