Refactor Jetpad Login into own client

This refactors the Jetpad interaction
into the Jetpad Client. We can then
reuse this client elsewhere in our
scripts.

Test: ./testReleaseNotes.py
Test: ./generateReleaseNotes.py 1593018000000
Change-Id: I55aabc5d2f74403211e2bceceab3055b24b16afc
diff --git a/development/JetpadClient.py b/development/JetpadClient.py
new file mode 100644
index 0000000..eedeb33
--- /dev/null
+++ b/development/JetpadClient.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2020 The Android Open Source 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 subprocess
+import datetime
+
+def getJetpadReleaseInfo(date):
+	try:
+		rawJetpadReleaseOutput = subprocess.check_output('span sql /span/global/androidx-jetpad:prod_instance \"SELECT GroupId, ArtifactId, ReleaseVersion, PreviousReleaseSHA, ReleaseSHA, Path, RequireSameVersionGroupBuild FROM LibraryReleases WHERE ReleaseDate = %s\"' % date, shell=True)
+	except subprocess.CalledProcessError:
+		print_e('FAIL: Failed to get jetpad release info for  %s' %  date)
+		return None
+	rawJetpadReleaseOutputLines = rawJetpadReleaseOutput.splitlines()
+	if len(rawJetpadReleaseOutputLines) <= 2:
+		print_e("Error: Date %s returned zero results from Jetpad.  Please check your date" % args.date)
+		return None
+	jetpadReleaseOutput = iter(rawJetpadReleaseOutputLines)
+	return jetpadReleaseOutput
+
+def getReleaseInfoObject(date, includeAllCommits, jetpadReleaseInfo):
+	releaseDateTime = datetime.datetime.fromtimestamp(float(date)/1000.0)
+	releaseJsonObject = {}
+	releaseJsonObject["releaseDate"] = "%02d-%02d-%s" % (releaseDateTime.month, releaseDateTime.day, releaseDateTime.year)
+	releaseJsonObject["includeAllCommits"] = includeAllCommits
+	releaseJsonObject["modules"] = {}
+	for line in jetpadReleaseInfo:
+		if "androidx" not in line.decode(): continue
+		# Remove all white space and split line based on '|'
+		artifactIdReleaseLine = line.decode().replace(" ", "").split('|')
+		groupId = artifactIdReleaseLine[1]
+		artifactId = artifactIdReleaseLine[2]
+		version = artifactIdReleaseLine[3]
+		fromSHA = artifactIdReleaseLine[4]
+		untilSHA = artifactIdReleaseLine[5]
+		path = artifactIdReleaseLine[6]
+		if path[0] == '/': path = path[1:]
+		requiresSameVersion = False
+		if artifactIdReleaseLine[7] == "true":
+			requiresSameVersion = True
+		if groupId in releaseJsonObject["modules"]:
+			releaseJsonObject["modules"][groupId].append({
+				"groupId": groupId,
+				"artifactId": artifactId,
+				"version": version,
+				"fromSHA": fromSHA,
+				"untilSHA": untilSHA,
+				"requiresSameVersion": requiresSameVersion,
+				"path": path
+			})
+		else:
+			releaseJsonObject["modules"][groupId] = [{
+				"groupId": groupId,
+				"artifactId": artifactId,
+				"version": version,
+				"fromSHA": fromSHA,
+				"untilSHA": untilSHA,
+				"requiresSameVersion": requiresSameVersion,
+				"path": path
+			}]
+	return releaseJsonObject
+
+def getJetpadRelease(date, includeAllCommits):
+	print("Getting the release info from Jetpad...")
+	jetpadReleaseInfo = getJetpadReleaseInfo(date)
+	if not jetpadReleaseInfo:
+		exit(1)
+	print("Successful")
+	return getReleaseInfoObject(date, includeAllCommits, jetpadReleaseInfo)
+