]> git.donarmstrong.com Git - cran2deb.git/blob - pkg/trunk/cran2deb
cran2deb: Debian version <-> R version infrastructure.
[cran2deb.git] / pkg / trunk / cran2deb
1 #!/usr/bin/env r
2
3 version.new <- function(rver,debian_revision=1, debian_epoch=0) {
4     # generate a string representation of the Debian version of an
5     # R version of a package
6     pkgver = rver
7
8     # Debian policy says that an upstream version should start with a digit and
9     # may only contain ASCII alphanumerics and '.+-:~'
10     if (!length(grep('^[0-9][A-Za-z0-9.+:~-]*$',rver))) {
11         stop(paste('R package version',rver
12                   ,'does not obviously translate into a valid Debian version.'))
13     }
14
15     # if rver contains a : then the Debian version must also have a colon
16     if (debian_epoch == 0 && length(grep(':',pkgver)))
17         debian_epoch = 1
18
19     # if the epoch is non-zero then include it
20     if (debian_epoch != 0)
21         pkgver = paste(debian_epoch,':',pkgver,sep='')
22
23     # always add the '-1' Debian release; nothing is lost and rarely will R
24     # packages be Debian packages without modification.
25     return(paste(pkgver,'-',debian_revision,sep=''))
26 }
27
28 version.epoch <- function(pkgver) {
29     # return the Debian epoch of a Debian package version
30     if (!length(grep(':',pkgver)))
31         return(0)
32     return(as.integer(sub('^([0-9]+):.*','\\1',pkgver)))
33 }
34 # version.epoch . version.new(x,y) = id
35 # version.epoch(version.new(x,y)) = 0
36
37 version.revision <- function(pkgver) {
38     # return the Debian revision of a Debian package version
39     return(as.integer(sub('.*-([0-9]+)$','\\1',pkgver)))
40 }
41 # version.revision . version.new(x) = id
42 # version.revision(version.new(x)) = 1
43
44 version.upstream <- function(pkgver) {
45     # return the upstream version of a Debian package version
46     return(sub('-[0-9]+$','',sub('^[0-9]+:','',pkgver)))
47 }
48 # version.upstream . version.new = id
49
50 version.update <- function(rver, prev_pkgver) {
51     prev_rver <- version.upstream(prev_pkgver)
52     if (prev_rver == rver) {
53         # increment the Debian revision
54         return(version.new(rver
55                           ,debian_revision = version.revision(prev_pkgver)+1
56                           ,debian_epoch    = version.epoch(prev_pkgver)
57                           ))
58     }
59     # new release
60     # TODO: implement Debian ordering over version and then autoincrement
61     #       Debian epoch when upstream version does not increment.
62     return(version.new(rver
63                       ,debian_epoch = version.epoch(prev_pkgver)
64                       ))
65 }
66
67 setup <- function() {
68     tmp <- tempfile('cran2deb')
69     dir.create(tmp)
70     return (tmp)
71 }
72
73 prepare.pkg <- function(dir, pkg, ...) {
74     # based loosely on library/utils/R/packages2.R::install.packages
75     archive <- download.packages(pkg, dir, type="source")[1,2]
76     wd <- getwd()
77     setwd(dir)
78     if (length(grep('\\.zip$',archive))) {
79         cmd = paste('unzip',shQuote(archive))
80     } else if (length(grep('\\.tar\\.gz$',archive))) {
81         cmd = paste('tar','xzf',shQuote(archive))
82     } else {
83         stop(paste('Type of archive',archive,'is unknown.'))
84     }
85     ret = system(cmd)
86     setwd(wd)
87     if (ret != 0) {
88         stop(paste('Extraction of archive',archive,'failed.'))
89     }
90     return (sub("_\\.(zip|tar\\.gz)", ""
91                ,gsub(.standard_regexps()$valid_package_version, ""
92                     ,archive)))
93 }
94
95 parse.description <- function(path) {
96     return (read.dcf(paste(path,'DESCRIPTION',sep='/')))
97 }
98
99 prepare.new.debian <- function(path, pkg, description) {
100     repo <- 'cran'
101     debdir <- paste(path,'debian',sep='/')
102     debfile <- function(x) { paste(debdir,x,sep='/') }
103     unlink(debdir,recursive=T)
104     dir.create(debdir)
105     cat(paste(paste(pkg,'(1.0) unstable; urgency=low'),''
106              ,'  * Initial release.',''
107              ,paste(' -- cran2deb <> ',format(Sys.time(),'%a, %d %b %Y %H:%M:%S %z'))
108              ,'',sep='\n'),file=debfile('changelog'))
109     cat(paste('#!/usr/bin/make -f'
110              ,'include /usr/share/R/debian/r-cran.mk'
111              ,'',sep='\n')
112        ,file=debfile('rules'))
113     cat(paste(paste("automatically created by cran2deb from",pkg)
114              ,paste('in the R repository',repo,'which has the following DESCRIPTION:')
115              ,'',sep='\n'),file=debfile('copyright'))
116     write.dcf(description,file=debfile('copyright'),append=T)
117     control = data.frame()
118     control[1,'Source'] = pkg
119     control[1,'Section'] = 'math'
120     control[1,'Priority'] = 'optional'
121     control[1,'Maintainer'] = 'cran2deb'
122     control[1,'Build-Depends-Indep'] = 'debhelper (>> 4.1.0), r-base-dev (>= 2.7.0), cdbs'
123     control[2,'Package'] = paste('r',repo,pkg,sep='-')
124     control[2,'Architecture'] = 'all'
125     control[2,'Depends'] = ''
126     control[2,'Description'] = paste(description[1,'Description'])
127     write.dcf(control,file=debfile('control'))
128     # TODO: debian/watch
129
130     invisible()
131 }
132
133 build.debian <- function(path) {
134     wd <- getwd()
135     setwd(path)
136     system('debuild')
137     setwd(wd)
138 }
139
140 cleanup <- function(dir) {
141     unlink(dir, recursive=T)
142
143     invisible()
144 }
145
146
147 test <- function(pkg) {
148     dir <- setup()
149         path <- prepare.pkg(dir,pkg)
150         description <- parse.description(path)
151         prepare.new.debian(path,pkg,description)
152         build.debian(path)
153     cleanup(dir)
154     return(description)
155 }
156