2016-11-11 00:10:25 -05:00
#!/usr/bin/env python3
2016-11-12 12:05:03 -05:00
import re
2016-11-11 21:55:53 -05:00
import os
2016-11-12 16:44:26 -05:00
import shutil
2016-11-11 21:55:53 -05:00
import subprocess
2016-11-13 16:09:16 -05:00
import hashlib
import urllib2
import git # python-gitpython in AUR
import menu3 # python-menu3 in AUR
import jinja2 # python-jinja in community
2016-11-12 16:44:26 -05:00
from tempfile import gettempdir
import pprint
2016-11-11 21:55:53 -05:00
2016-11-11 00:10:25 -05:00
## SETTINGS ##
2016-11-13 16:09:16 -05:00
gpgkey = [ ' 748231EBCBD808A14F5E85D28C004C2F93481F6B ' ] # https://wiki.archlinux.org/index.php/PKGBUILD#validpgpkeys
2016-11-11 00:10:25 -05:00
maintname = ' brent s. <bts[at]square-r00t[dot]net> ' # your name and email address, feel free to obfuscate though
pkgbuild_dir = ' /opt/dev/arch ' # what dir do the pkgbuilds/AUR checkouts live?
aur_pkgs_dir = pkgbuild_dir # should be the dir where the aur_pkgs repo checkout lives. it's recommended you keep this the same as pkgbuild_dir
2016-11-11 21:55:53 -05:00
## BUILD THE GUI ##
def gui_init ( ) :
2016-11-12 12:05:03 -05:00
m = menu3 . Menu ( True )
pkgname = False
base_options = [ " Add a new package to the AUR... " ,
" Sign a package ' s sources " ,
" Update/initialize submodules from your AUR account " ]
base_menu = m . menu ( " How might I assist you today? " , base_options , " Select an operation ( ' q ' to quit): " )
pkg = { }
if base_menu == 1 :
add_options = [ " Release/versioned " ,
" VCS (Git, SVN, Mercurial, etc.) " ]
add_menu = m . menu ( " What type of package is this? " , add_options , " Package type ( ' q ' to quit): " )
elif base_menu == 2 :
pkg [ ' oper ' ] = ' sign '
elif base_menu == 3 :
pkg [ ' oper ' ] = ' submodule '
# If they selected to add a package and it's a VCS package...
if add_menu == 2 :
vcs_options = [ " Git " ,
" Subversion (svn) " ,
" Mercurial (hg) " ,
" Bazaar (bzr) " ]
vcs_menu = m . menu ( " What type of VCS system? " , vcs_options , " VCS type ( ' q ' to quit): " )
2016-11-13 16:09:16 -05:00
pkg [ ' name ' ] = input ( " \n What is the name of your package? (Exclude the ' -git ' etc. suffix, that will be added automatically later on) \n " ) . lower ( )
2016-11-12 12:05:03 -05:00
srcurl = input ( " \n What is the checkout URL for {0} ? \n (Do not include the directory or VCS type prefix as per \n https://wiki.archlinux.org/index.php/VCS_package_guidelines#VCS_sources ... \n it will be added automatically) \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' vcstype ' ] = [ " git " ,
" svn " ,
" hg " ,
" bzr " ]
pkg [ ' srcurl ' ] = pkg [ ' name ' ] + " :: " + pkg [ ' vcstype ' ] [ vcs_menu - 1 ] + srcurl
2016-11-13 16:09:16 -05:00
pkg [ ' name ' ] = pkg [ ' name ' ] + " - " + pkg [ ' vcstype ' ]
pkg [ ' type ' ] = ' vcs '
2016-11-12 12:05:03 -05:00
pkg [ ' srcfile ' ] = False
pkg [ ' ver ' ] = False
2016-11-13 16:09:16 -05:00
pkg [ ' srchash ' ] = ' SKIP '
pkg [ ' src_dl ' ] = False
2016-11-12 12:05:03 -05:00
# If they're adding a release package...
elif add_menu == 1 :
pkg [ ' vcstype ' ] = False
pkg [ ' name ' ] = input ( " \n What is the name of your package? \n " ) . lower ( )
pkg [ ' ver ' ] = input ( " \n What is the version of the release you are packaging for {0} ? \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' srcurl ' ] = input ( " \n What is the full URL for the tarball/zip file/etc. for {0} (version {1} )? \n " . format ( pkg [ ' name ' ] , pkg [ ' ver ' ] ) )
pkg [ ' srcfile ' ] = re . sub ( ' ^ \ s*(https?|ftp).*/(.*) \ s*$ ' , ' \\ 2 ' , pkg [ ' srcurl ' ] , re . IGNORECASE )
2016-11-13 16:09:16 -05:00
pkg [ ' type ' ] = ' release '
# And here's where we download the source file for hashing
pkg [ ' src_dl ' ] = gettempdir ( ) + " / " + pkg [ ' srcfile ' ]
print ( " Please wait while we download {0} to {1} ... \n " . format ( pkg [ ' srcfile ' ] , pkg [ ' src_dl ' ] ) )
datastream = urllib2 . urlopen ( pkg [ ' srcurl ' ] )
data_in = datastream . read ( )
with open ( pkg [ ' src_dl ' ] , " wb " ) as data_dl :
data_dl . write ( data_in )
pkg [ ' srchash ' ] = hashlib . sha512 ( open ( pkg [ ' src_dl ' ] , ' rb ' ) . read ( ) ) . hexdigest ( )
2016-11-12 12:05:03 -05:00
# And this is stuff shared by both types.
pkg [ ' desc ' ] = input ( " \n What is a short description of {0} ? \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' site ' ] = input ( " \n What is {0} ' s website? \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' license ' ] = [ ]
license_raw = input ( " \n What is {0} ' s license(s)? (See https://wiki.archlinux.org/index.php/PKGBUILD#license) \n If you have more than one, separate them by spaces. \n " . format ( pkg [ ' name ' ] ) . upper ( ) )
pkg [ ' license ' ] = list ( map ( str , license_raw . split ( ) ) )
pkg [ ' deps ' ] = [ ]
deps_raw = input ( " \n What does {0} depend on for runtime? if no packages, just hit enter. \n Make sure they correspond to Arch/AUR package names. \n If you have more than one, separate them by spaces. \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' deps ' ] = list ( map ( str , deps_raw . split ( ) ) )
pkg [ ' optdeps ' ] = [ ]
optdeps_raw = input ( " \n What does {0} optionally depend on (runtime)? if no packages, just hit enter. \n Make sure they correspond to Arch/AUR package names. \n If you have more than one, separate them by COMMAS. \n They should follow this format: \n pkgname: some reason why it should be installed \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' optdeps ' ] = list ( map ( str , optdeps_raw . split ( ' , ' ) ) )
pkg [ ' makedeps ' ] = [ ]
makedeps_raw = input ( " \n What dependencies are required for building/making {0} ? If no packages, just hit enter. \n Make sure they correspond to Arch/AUR package names. \n If you have more than one, separate them by spaces. \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' makedeps ' ] = list ( map ( str , makedeps_raw . split ( ) ) )
pkg [ ' provides ' ] = [ ]
provides_raw = input ( " \n What package names, if any besides itself, does {0} provide? \n (If {0} is a VCS package, do NOT include the non-VCS package name- that ' s added by default!) \n If you have more than one, separate them by spaces. \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' provides ' ] = list ( map ( str , provides_raw . split ( ) ) )
pkg [ ' conflicts ' ] = [ ]
conflicts_raw = input ( " \n What package names, if any, does {0} conflict with? \n (If {0} is a VCS package, do NOT include the non-VCS package name- that ' s added by default!) \n If you have more than one, separate them by spaces. \n " . format ( pkg [ ' name ' ] ) )
pkg [ ' conflicts ' ] = list ( map ( str , conflicts_raw . split ( ) ) )
return ( pkg )
2016-11-12 16:44:26 -05:00
## MAKE SURE SOME PREREQS HAPPEN ##
def sanity_checks ( pkg ) :
try :
os . makedirs ( pkgbuild_dir )
except OSError as exception :
if exception . errno != errno . EEXIST :
raise
2016-11-13 16:09:16 -05:00
## REGISTER IN THE AUR AND MAKE FIRST COMMIT ##
2016-11-12 16:44:26 -05:00
def aur_create ( pkg ) :
2016-11-13 16:09:16 -05:00
# git clone from AUR to create repository, add .gitignore
tmpcheckout = os . path . join ( gettempdir ( ) , ' .aur_pkgs ' )
repo_dir = tmpcheckout + ' / ' + pkg [ ' name ' ]
aur_repo = git . Repo . clone_from ( ' aur@aur.archlinux.org: ' + pkg [ ' name ' ] , git . osp . join ( tmpcheckout , pkg [ ' name ' ] ) , branch = ' master ' )
2016-11-12 16:44:26 -05:00
shutil . copy2 ( aur_pkgs_dir + " /_docs/PKGBUILD.templates.d/gitignore " , tmpcheckout + " /.gitignore " )
2016-11-13 16:09:16 -05:00
aur_repo . index . add ( ' .gitignore ' )
# Create the initial PKGBUILD
tpl_dir = aur_pkgs_dir + ' /_docs/PKGBUILD.templates.d.python '
tpl_meta = aur_pkgs_dir + ' /_docs/PKGBUILD.templates.d.python ' + ' / ' + pkg [ ' type ' ] + ' .all '
tpl_fsloader = jinja2 . FileSystemLoader ( searchpath = tpl_dir , followlinks = True )
tpl_fsloader2 = jinja2 . FileSystemLoader ( searchpath = tpl_dir + ' / ' + pkg [ ' type ' ] , followlinks = True )
pkgbuild_list = tpl_fsloader2 . list_templates ( )
pkgbuild_list [ : ] = [ pkg [ ' type ' ] + ' / ' + s for s in pkgbuild_list ]
tpl_env = jinja2 . Environment ( loader = tpl_fsloader )
pkgbuild_out = tpl_env . get_template ( pkg [ ' type ' ] + ' .all.j2 ' ) . render ( pkg = pkg , maintname = maintname , gpgkey = gpgkey , pkgbuild_list = pkgbuild_list )
with open ( repo_dir + " /PKGBUILD " , " wb " ) as pkgbuild_file :
pkgbuild_file . write ( pkgbuild_out )
# Move the source file
if pkg [ ' srcfile ' ] :
os . rename ( pkg [ ' src_dl ' ] , repodir + ' / ' + pkg [ ' srcfile ' ] )
gpg = gnupg . GPG ( )
datastream = open ( pkg [ ' dl_src ' ] , ' rb ' )
gpg . sign_file ( datastream , keyid = gpgkey [ 0 ] , detach = True , clearsign = False , output = repodir + ' / ' + pkg [ ' srcfile ' ] + ' .sig ' )
datastream . close ( )
aur . repo . indes . add ( pkg [ ' srcfile ' ] + ' .sig ' )
aur . repo . index . add ( ' PKGBUILD ' )
# commit to git
aur_repo . index . commit ( " initial commit; setting up .gitignores and skeleton PKGBUILD " )
# and push...
aur_repo . push ( )
2016-11-12 16:44:26 -05:00
2016-11-12 12:05:03 -05:00
pprint . pprint ( gui_init ( ) )
2016-11-13 16:09:16 -05:00
#aur_create(gui_init())