-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from jimisola/main
Adds support for base64 and OAuth bearer tokens
- Loading branch information
Showing
9 changed files
with
182 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
#!/bin/env python | ||
|
||
import argparse | ||
import os | ||
import sys | ||
import textwrap | ||
from maven_artifact.artifact import Artifact | ||
|
||
try: | ||
from maven_artifact.utils import Utils | ||
except ImportError: | ||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) | ||
from maven_artifact.utils import Utils | ||
|
||
from maven_artifact.requestor import RequestException | ||
from maven_artifact.downloader import Downloader | ||
|
||
|
||
class DescriptionWrappedNewlineFormatter(argparse.HelpFormatter): | ||
"""An argparse formatter that: | ||
* preserves newlines (like argparse.RawDescriptionHelpFormatter), | ||
* removes leading indent (great for multiline strings), | ||
* and applies reasonable text wrapping. | ||
Source: https://stackoverflow.com/a/64102901/79125 | ||
""" | ||
|
||
def _fill_text(self, text, width, indent): | ||
# Strip the indent from the original python definition that plagues most of us. | ||
text = textwrap.dedent(text) | ||
text = textwrap.indent(text, indent) # Apply any requested indent. | ||
text = text.splitlines() # Make a list of lines | ||
text = [textwrap.fill(line, width) for line in text] # Wrap each line | ||
text = "\n".join(text) # Join the lines again | ||
return text | ||
|
||
|
||
class WrappedNewlineFormatter(DescriptionWrappedNewlineFormatter): | ||
"""An argparse formatter that: | ||
* preserves newlines (like argparse.RawTextHelpFormatter), | ||
* removes leading indent and applies reasonable text wrapping (like DescriptionWrappedNewlineFormatter), | ||
* applies to all help text (description, arguments, epilogue). | ||
""" | ||
|
||
def _split_lines(self, text, width): | ||
# Allow multiline strings to have common leading indentation. | ||
text = textwrap.dedent(text) | ||
text = text.splitlines() | ||
lines = [] | ||
for line in text: | ||
wrapped_lines = textwrap.fill(line, width).splitlines() | ||
lines.extend(subline for subline in wrapped_lines) | ||
if line: | ||
lines.append("") # Preserve line breaks. | ||
return lines | ||
|
||
|
||
class MainCommand: | ||
def _get_arguments(self): | ||
parser = argparse.ArgumentParser(formatter_class=WrappedNewlineFormatter, epilog=__epilog__) | ||
parser.add_argument( | ||
"maven_coordinate", | ||
help=""" | ||
defined by http://maven.apache.org/pom.html#Maven_Coordinates. The possible options are: | ||
- groupId:artifactId:version | ||
- groupId:artifactId:packaging:version | ||
- groupId:artifactId:packaging:classifier:version""", | ||
) | ||
parser.add_argument( | ||
"filename", | ||
nargs="?", | ||
help=""" | ||
If not supplied the filename will be <artifactId>.<extension>. | ||
The filename directory must exist prior to download.""", | ||
) | ||
parser.add_argument( | ||
"-m", | ||
"--maven-repo", | ||
dest="base", | ||
default="https://repo.maven.apache.org/maven2/", | ||
help="Maven repository URL (default: https://repo.maven.apache.org/maven2/)", | ||
) | ||
|
||
parser.add_argument("-u", "--username", help="username (must be combined with --password)") | ||
parser.add_argument( | ||
"-p", | ||
"--password", | ||
help=""" | ||
password (must be combined with --username) or | ||
base64 encoded username and password (can not not be combined with --username)""", | ||
) | ||
parser.add_argument( | ||
"-t", "--token", help="OAuth bearer token (can not be combined with --username or --password)" | ||
) | ||
|
||
parser.add_argument("-ht", "--hash-type", default="md5", help="hash type (default: md5)") | ||
|
||
args = parser.parse_args() | ||
|
||
username = args.username | ||
password = args.password | ||
token = args.token | ||
|
||
if username and not password: | ||
parser.error("The 'username' parameter requires the 'password' parameter.") | ||
elif (username or password) and token: | ||
parser.error("The 'token' parameter cannot be used together with 'username' or 'password'.") | ||
elif (password) and not (username or token) and not Utils.is_base64(password): | ||
parser.error("The 'password' parameter must be base64 if not used together with 'username'.") | ||
|
||
return args | ||
|
||
|
||
__epilog__ = """ | ||
Example: | ||
%(prog)s "org.apache.solr:solr:war:3.5.0"\n | ||
""" | ||
|
||
|
||
def main(): | ||
mc = MainCommand() | ||
args = mc._get_arguments() | ||
|
||
try: | ||
dl = Downloader(base=args.base, username=args.username, password=args.password, token=args.token) | ||
|
||
artifact = Artifact.parse(args.maven_coordinate) | ||
|
||
filename = args.filename | ||
|
||
if dl.download(artifact, filename, args.hash_type): | ||
sys.exit(0) | ||
else: | ||
print("Download failed.") | ||
sys.exit(1) | ||
except RequestException as e: | ||
print(e.msg) | ||
sys.exit(1) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import base64 | ||
|
||
|
||
class Utils: | ||
@staticmethod | ||
def is_base64(sb): | ||
try: | ||
if isinstance(sb, str): | ||
# If there's any unicode here, an exception will be thrown and the function will return false | ||
sb_bytes = bytes(sb, "ascii") | ||
elif isinstance(sb, bytes): | ||
sb_bytes = sb | ||
else: | ||
raise ValueError("Argument must be string or bytes") | ||
return base64.b64encode(base64.b64decode(sb_bytes)) == sb_bytes | ||
except Exception: | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters