Compare commits
No commits in common. "07988a5ca83511dccbafa2490c79c1ae820c8090" and "a1613489c476a6fd4c21f2241e32d7c490281aa3" have entirely different histories.
07988a5ca8
...
a1613489c4
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,7 +22,6 @@
|
|||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
|
|
||||||
signature.conf
|
|
||||||
secret.txt
|
secret.txt
|
||||||
|
|
||||||
.sign.conf
|
.sign.conf
|
||||||
|
6
.project
6
.project
@ -5,13 +5,7 @@
|
|||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
<buildSpec>
|
<buildSpec>
|
||||||
<buildCommand>
|
|
||||||
<name>org.python.pydev.PyDevBuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>org.python.pydev.pythonNature</nature>
|
|
||||||
</natures>
|
</natures>
|
||||||
</projectDescription>
|
</projectDescription>
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python interpreter</pydev_property>
|
|
||||||
</pydev_project>
|
|
278
bin/gpgsign.py
278
bin/gpgsign.py
@ -1,278 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
|
|
||||||
gpgsign.py - Helper to "GPG" sign Mylyn Gitea Release files
|
|
||||||
|
|
||||||
Limitations:
|
|
||||||
Too many limitations to be listed here.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
1. Set GPG configuration in signature.conf file
|
|
||||||
2. run gpgsign.py
|
|
||||||
|
|
||||||
Caveats:
|
|
||||||
Must be run AFTER jarsign.sh to avoid gpg signature modification
|
|
||||||
|
|
||||||
Generated files are similar to maven-gpg-plugin ones (default configuration)
|
|
||||||
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
import subprocess
|
|
||||||
from pathlib import Path, PurePath
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from typing import Tuple
|
|
||||||
from enum import Enum
|
|
||||||
import configparser
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=logging-fstring-interpolation, line-too-long
|
|
||||||
|
|
||||||
__PROG__ = "gpgsign"
|
|
||||||
|
|
||||||
WORKSPACEDIR = Path(__file__).parent.parent # <workspace>/bin/gpgsign.py
|
|
||||||
ASC_DIRECTORY = "gpg"
|
|
||||||
|
|
||||||
class GPGLockMode(Enum):
|
|
||||||
ONCE = "once"
|
|
||||||
MULTIPLE = "multiple"
|
|
||||||
NEVER = "never"
|
|
||||||
@dataclass
|
|
||||||
class GPGConfiguration:
|
|
||||||
keyname: str
|
|
||||||
passphrase: str = ""
|
|
||||||
verbose:bool = False
|
|
||||||
skip: bool = False
|
|
||||||
interactive : bool = True
|
|
||||||
executable : Path = None
|
|
||||||
use_agent: bool = False
|
|
||||||
home_dir: str = ""
|
|
||||||
secret_keyring : str = ""
|
|
||||||
public_keyring : str = ""
|
|
||||||
lock_mode : GPGLockMode = None # gpg lock mode, could be : None -> lock mode not used, "once", "multiple", "never" => SyntaxError
|
|
||||||
args = "" # list, of additional arguments as list or tuple or comma separated as string
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Configuration:
|
|
||||||
gpg: GPGConfiguration
|
|
||||||
|
|
||||||
class GPGSigner:
|
|
||||||
"""Compute signature.
|
|
||||||
"""
|
|
||||||
SIGNATURE_EXTENSION : str = ".asc"
|
|
||||||
|
|
||||||
def __init__(self, gpg:GPGConfiguration , output_dir: Path ):
|
|
||||||
self.output_dir = output_dir
|
|
||||||
self.gpg = gpg
|
|
||||||
self.interactive = False
|
|
||||||
|
|
||||||
def generate_signature_for_file(self, file: Path, signature: Path) -> int:
|
|
||||||
"""Generate a detached signature file for provided file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
file: Path of file to be signed
|
|
||||||
signature: Path of file where the signature will be written.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
return code of signature application
|
|
||||||
"""
|
|
||||||
# Configure command line
|
|
||||||
cmd = ['gpg']
|
|
||||||
if self.gpg.executable:
|
|
||||||
cmd = [str(self.gpg.executable)]
|
|
||||||
|
|
||||||
if self.gpg.args:
|
|
||||||
if isinstance(self.gpg.args, (list, tuple)):
|
|
||||||
cmd += self.gpg.args
|
|
||||||
else:
|
|
||||||
cmd += self.gpg.args.split(",")
|
|
||||||
|
|
||||||
if self.gpg.verbose:
|
|
||||||
cmd.append("-v")
|
|
||||||
|
|
||||||
if self.gpg.home_dir:
|
|
||||||
cmd += [ "--homedir", self.gpg.home_dir]
|
|
||||||
|
|
||||||
cmd.append(f"--{'' if self.gpg.use_agent else 'no-'}use-agent")
|
|
||||||
|
|
||||||
# required for subprocess input:
|
|
||||||
# 1. to disable input when self.gpg.passphrase is "" (run is waiting None)
|
|
||||||
# 2. run is waiting bytes for input
|
|
||||||
in_passphrase=None
|
|
||||||
if self.gpg.passphrase:
|
|
||||||
cmd += ["--batch", "--passphrase-fd", "0"]
|
|
||||||
in_passphrase = bytes(self.gpg.passphrase,"UTF-8")
|
|
||||||
|
|
||||||
if self.gpg.keyname:
|
|
||||||
cmd += ["--local-user", self.gpg.keyname]
|
|
||||||
|
|
||||||
cmd.append("--armor")
|
|
||||||
cmd.append("--detach-sign")
|
|
||||||
|
|
||||||
if not self.gpg.interactive:
|
|
||||||
cmd.append("--no-tty") #
|
|
||||||
|
|
||||||
if self.gpg.secret_keyring or self.gpg.public_keyring:
|
|
||||||
cmd.append("--no-default-keyring")
|
|
||||||
|
|
||||||
if self.gpg.secret_keyring:
|
|
||||||
cmd += ["--secret-keyring", self.gpg.secret_keyring]
|
|
||||||
|
|
||||||
if self.gpg.public_keyring:
|
|
||||||
cmd +=[ "--keyring", self.gpg.public_keyring]
|
|
||||||
|
|
||||||
if self.gpg.lock_mode:
|
|
||||||
cmd.append(f"--lock-{self.gpg.lock_mode}")
|
|
||||||
|
|
||||||
cmd += ["--output", str(signature)]
|
|
||||||
|
|
||||||
cmd.append(str(file))
|
|
||||||
|
|
||||||
logging.debug(f"GPGSigner> {cmd}")
|
|
||||||
|
|
||||||
# Execute command line
|
|
||||||
completed_process = subprocess.run(cmd, input=in_passphrase)
|
|
||||||
|
|
||||||
logging.debug(str(completed_process))
|
|
||||||
|
|
||||||
return completed_process.returncode
|
|
||||||
|
|
||||||
def generate_signature_for_artifact (self, file: Path) -> int:
|
|
||||||
"""Create a detached signature file for the provided file
|
|
||||||
managing valide signature file destination.
|
|
||||||
"""
|
|
||||||
# Setup file and directory for signature
|
|
||||||
|
|
||||||
signature = file.with_suffix ( file.suffix + GPGSigner.SIGNATURE_EXTENSION)
|
|
||||||
|
|
||||||
if self.output_dir:
|
|
||||||
|
|
||||||
# ugly but working way to get common parts
|
|
||||||
for i,part in enumerate(signature.parts):
|
|
||||||
try:
|
|
||||||
if part == self.output_dir.parts[i]:
|
|
||||||
continue
|
|
||||||
except IndexError: # output_dir is smaller than signature
|
|
||||||
pass
|
|
||||||
break
|
|
||||||
|
|
||||||
common_dir = Path(*signature.parts[:i])
|
|
||||||
|
|
||||||
if common_dir:
|
|
||||||
signature = self.output_dir / signature.relative_to(common_dir)
|
|
||||||
|
|
||||||
# Create destination directory
|
|
||||||
logging.debug(f"GPGSigner> artifact:{file}")
|
|
||||||
logging.debug(f"GPGSigner> signature:{signature}")
|
|
||||||
if not signature.parent.is_dir():
|
|
||||||
signature.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
if signature.exists():
|
|
||||||
signature.unlink()
|
|
||||||
|
|
||||||
# Generate signature file
|
|
||||||
return self.generate_signature_for_file(file, signature)
|
|
||||||
|
|
||||||
def get_passphrase(self):
|
|
||||||
return ""
|
|
||||||
|
|
||||||
class Project:
|
|
||||||
""" Project as list of artifacts """
|
|
||||||
ARTIFACTS_EXTENSIONS = ('.jar', '.xml', '.md')
|
|
||||||
DEFAULT_EXCLUDES = ('.asc', ".gpg", ".sig", ".git", ".externalToolBuilders")
|
|
||||||
|
|
||||||
def __init__(self, projectdir):
|
|
||||||
self.projectdir = projectdir
|
|
||||||
logging.debug(f"Project> {projectdir}")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
return self.projectdir.name
|
|
||||||
|
|
||||||
def get_attached_artifacts(self, iter_in_dir :Path = None) -> Path:
|
|
||||||
"""
|
|
||||||
Yields:
|
|
||||||
artifact
|
|
||||||
"""
|
|
||||||
iter_in_dir = self.projectdir if iter_in_dir is None else iter_in_dir
|
|
||||||
for e in iter_in_dir.iterdir():
|
|
||||||
if e.is_dir() :
|
|
||||||
logging.debug(f"Project.get_artifacts> entering in {str(e)}")
|
|
||||||
yield from self.get_attached_artifacts(e)
|
|
||||||
if e.suffix.lower() in Project.DEFAULT_EXCLUDES:
|
|
||||||
logging.debug(f"Project.get_artifacts> excluding {e}")
|
|
||||||
continue
|
|
||||||
if e.suffix.lower() in Project.ARTIFACTS_EXTENSIONS or e.name == 'LICENSE':
|
|
||||||
logging.debug(f"Project.get_artifacts> {e}")
|
|
||||||
yield e
|
|
||||||
|
|
||||||
class GPGSignAttached:
|
|
||||||
"""Sign artifacts attached to the project."""
|
|
||||||
def __init__(self, project: Project, config: Configuration):
|
|
||||||
self.project = project
|
|
||||||
self.config = config
|
|
||||||
|
|
||||||
def execute(self):
|
|
||||||
if self.config.gpg.skip:
|
|
||||||
logging.warning(f"GPGSign> Skipping GPG Signature for {self.project.name}")
|
|
||||||
return
|
|
||||||
|
|
||||||
logging.info(f"GPGSign> Signing {self.project.name} artifacts")
|
|
||||||
signer = GPGSigner(config.gpg, self.project.projectdir / ASC_DIRECTORY)
|
|
||||||
for artifact in self.project.get_attached_artifacts():
|
|
||||||
signer.generate_signature_for_artifact(artifact)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# pylint: disable=invalid-name
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
# backup working directory
|
|
||||||
OLDPWD = os.path.curdir
|
|
||||||
|
|
||||||
# Configure the command line arguments parser
|
|
||||||
parser = argparse.ArgumentParser(prog=__PROG__,
|
|
||||||
description=__PROG__ + " Sign (Java + GPG) updatesite artifacts",
|
|
||||||
prefix_chars="-+")
|
|
||||||
|
|
||||||
parser.add_argument("-c", "--config-file",
|
|
||||||
help="Configuration file (default <workspacedir>/signature.conf",
|
|
||||||
dest="config_file",
|
|
||||||
default=str((WORKSPACEDIR / "signature.conf").absolute()),
|
|
||||||
required=False)
|
|
||||||
|
|
||||||
parser.add_argument("-x",
|
|
||||||
help="Active 'debug' level for logging",
|
|
||||||
dest='debug',
|
|
||||||
action='store_true',
|
|
||||||
default=False,
|
|
||||||
required=False)
|
|
||||||
|
|
||||||
# Parse the command line
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# Configuration file
|
|
||||||
config_ini = configparser.ConfigParser()
|
|
||||||
config_ini.read(args.config_file)
|
|
||||||
config = Configuration(
|
|
||||||
gpg=GPGConfiguration(
|
|
||||||
skip = config_ini.getboolean('GPG','skip', fallback=True),
|
|
||||||
verbose = config_ini.getboolean('GPG','verbose', fallback=False),
|
|
||||||
keyname = config_ini.get('GPG', 'keyname', fallback=None),
|
|
||||||
passphrase= config_ini.get('GPG','passphrase', fallback=None),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Configure logging
|
|
||||||
# see https://docs.python.org/2/howto/logging.html
|
|
||||||
logging.basicConfig(
|
|
||||||
format='%(asctime)s:%(levelname)s:%(message)s' if args.debug else '%(levelname)s:%(message)s',
|
|
||||||
level=logging.DEBUG if args.debug else logging.INFO)
|
|
||||||
|
|
||||||
siteupdate_project = Project(WORKSPACEDIR / "io.gitea.mylyn.updatesite")
|
|
||||||
GPGSignAttached(siteupdate_project, config).execute()
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# vim: tabstop=4:shiftwidth=4:expandtab
|
|
@ -1,55 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Helper script to sign Mylyn Gitea eclipse plugin
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# 1. Configure the .sign.conf file
|
|
||||||
# 2. jarsign.sh [-x]
|
|
||||||
#
|
|
||||||
# Inspired from https://nirmalsasidharan.wordpress.com/2010/09/04/signing_eclipse_plugins/
|
|
||||||
#
|
|
||||||
|
|
||||||
# set debug
|
|
||||||
case "x$1" in "x-x" ) shift ; set -x ;; esac
|
|
||||||
|
|
||||||
#
|
|
||||||
# Sign all "not already signed" jar in a directory
|
|
||||||
# usage: jarsign_dir <directory>
|
|
||||||
#
|
|
||||||
jarsign_dir() {
|
|
||||||
for jarfile in ${1}/*.jar ; do
|
|
||||||
[ -e "$jarfile" ] || continue
|
|
||||||
unset result
|
|
||||||
case ${result:-$(jarsigner -verify -verbose ${opt_keystore} ${opt_storepass} ${opt_alias} ${jarfile} ${KEYALIAS} | egrep 'jar is unsigned|jar verified')} in
|
|
||||||
'jar is unsigned.' )
|
|
||||||
jarsigner ${opt_keystore} ${opt_storepass} -verbose ${opt_alias} ${jarfile} ${KEYALIAS} ;;
|
|
||||||
'jar verified.' )
|
|
||||||
echo "$jarfile already signed"
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
echo "***ERROR Raised by ${jarfile} signature verification..."
|
|
||||||
echo $result
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
WORKSPACEDIR=$(realpath "$(dirname $0)/.." )
|
|
||||||
SIGNPARAMS=${WORKSPACEDIR}/.sign.conf
|
|
||||||
if [ -x $SIGNPARAMS ] ; then
|
|
||||||
source $SIGNPARAMS
|
|
||||||
else
|
|
||||||
echo "Missing configuration file" && exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (( $JARSIGN == 1)) ; then
|
|
||||||
[ -f "${KEYSTORE}" ] && opt_keystore="-keystore ${KEYSTORE}"
|
|
||||||
[ -n "${STOREPASS}" ] && opt_storepass="-storepass ${STOREPASS}"
|
|
||||||
|
|
||||||
jarsign_dir ${WORKSPACEDIR}/io.gitea.mylyn.updatesite
|
|
||||||
jarsign_dir ${WORKSPACEDIR}/io.gitea.mylyn.updatesite/features
|
|
||||||
jarsign_dir ${WORKSPACEDIR}/io.gitea.mylyn.updatesite/plugins
|
|
||||||
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: Mylyn Gitea Connector Core
|
Bundle-Name: Mylyn Gitea Connector Core
|
||||||
Bundle-SymbolicName: io.gitea.mylyn.core;singleton:=true
|
Bundle-SymbolicName: io.gitea.mylyn.core;singleton:=true
|
||||||
Bundle-Version: 0.3.1
|
Bundle-Version: 0.2.0
|
||||||
Bundle-Activator: io.gitea.mylyn.core.GiteaPluginCore
|
Bundle-Activator: io.gitea.mylyn.core.GiteaPluginCore
|
||||||
Bundle-Vendor: io.gitea
|
Bundle-Vendor: io.gitea
|
||||||
Require-Bundle: org.eclipse.core.runtime,
|
Require-Bundle: org.eclipse.core.runtime,
|
||||||
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: %Bundle-Name
|
Bundle-Name: %Bundle-Name
|
||||||
Bundle-SymbolicName: io.gitea.mylyn.ui;singleton:=true
|
Bundle-SymbolicName: io.gitea.mylyn.ui;singleton:=true
|
||||||
Bundle-Version: 0.3.1
|
Bundle-Version: 0.2.0
|
||||||
Automatic-Module-Name: io.gitea.mylyn.ui
|
Automatic-Module-Name: io.gitea.mylyn.ui
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||||
Bundle-Activator: io.gitea.mylyn.ui.GiteaUIPlugin
|
Bundle-Activator: io.gitea.mylyn.ui.GiteaUIPlugin
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
[JARSIGN]
|
|
||||||
skip:false
|
|
||||||
keyname:
|
|
||||||
storepass:
|
|
||||||
keystore:
|
|
||||||
|
|
||||||
[GPG]
|
|
||||||
skip=false
|
|
||||||
keyname:
|
|
||||||
passphrase:
|
|
||||||
verbose:
|
|
Loading…
Reference in New Issue
Block a user