Skip to content

Commit f0f6dcc

Browse files
authored
Merge pull request #6 from pedia/0.3.1
Add NPM/YUM/Rustup
2 parents 71a6ab1 + 4216b74 commit f0f6dcc

14 files changed

Lines changed: 643 additions & 84 deletions

File tree

.gitignore

Lines changed: 0 additions & 7 deletions
This file was deleted.

README.md

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,101 @@
11
# repocache
2-
Universal caching and proxying server for pypi/maven, speedup local using.
2+
Universal caching and proxying repository server for pypi/maven/npm/yum/rustup, speedup local using.
33

4-
## How to use repocache for mvn?
5-
```shell
4+
## How to startup?
5+
```bash
66
pip install repocache
77

8-
python -m repocache.main --cache-folder=/tmp --mvn_upstream=http://maven.aliyun.com/nexus/content/groups/public
8+
python -m repocache.main -f default.cfg
9+
# listen at 0.0.0.0:5000
10+
```
11+
12+
## How to use repocache as YUM repository?
13+
```bash
14+
cd /etc/yum.repos.d
15+
16+
# base
17+
curl -O http://192.168.1.2:5000/centos/huawei/Centos-7.repo
18+
# sclo
19+
curl -O http://192.168.1.2:5000/centos/sclo/Centos-7.repo
20+
21+
yum makecache
922
```
1023

11-
Change ~/.m2/settings.xml as:
24+
## How to use repocache as NPM repository?
25+
```bash
26+
npm config set registry https://127.0.0.1:5000/npm/default/
27+
npm config set prefix=$HOME/.node_modules_global
28+
npm --verbose install smallest-png@2.0.0 -g
29+
```
30+
31+
## How to use repocache as MVN repository?
32+
33+
Change $HOME/.m2/settings.xml as:
1234
```xml
1335
<?xml version="1.0" encoding="UTF-8"?>
1436
<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1537
xmlns="http://maven.apache.org/SETTINGS/1.0.0"
1638
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
39+
<profiles>
40+
<profile>
41+
<id>repocache</id>
42+
<repositories>
43+
<repository>
44+
<id>repocache</id>
45+
<url>http://127.0.0.1:5000/mvn/default/</url>
46+
</repository>
47+
<repository>
48+
<id>jitpack.io</id>
49+
<url>http://127.0.0.1:5000/mvn/jitpack/</url>
50+
</repository>
51+
</repositories>
52+
</profile>
53+
</profiles>
54+
<activeProfiles>
55+
<activeProfile>repocache</activeProfile>
56+
</activeProfiles>
1757
<mirrors>
1858
<mirror>
1959
<id>repocache</id>
20-
<name>repo-local-mirror</name>
21-
<url>http://127.0.0.1:5000/mvn/public</url>
60+
<url>http://127.0.0.1:5000/mvn/default/</url>
2261
<mirrorOf>central</mirrorOf>
2362
</mirror>
2463
</mirrors>
2564
</settings>
2665
```
2766

28-
## How to use repocache for pip?
2967
```shell
30-
pip install repocache
31-
32-
python -m repocache.main --cache-folder=/tmp
68+
cd /path/to/java-project
69+
mvn install
3370
```
3471

35-
```shell
72+
73+
74+
## How to use repocache as PIP repository?
75+
Simply install in shell:
76+
```bash
3677
pip install -i http://127.0.0.1:5000/pypi/simple --trusted-host=127.0.0.1:5000 click==7.1.2
3778
```
3879

39-
Or change ~/.pip/pip.conf as:
80+
Or change $HOME/.pip/pip.conf as:
4081
```
4182
[global]
4283
trusted-host=127.0.0.1:5000
4384
index-url=http://127.0.0.1:5000/pypi/simple
4485
```
4586

46-
## Settting file
47-
See default.cfg
48-
87+
## How to use repocache as Rustup?
88+
```bash
89+
export RUSTUP_DIST_SERVER=http://127.0.0.1:5000/rust/default
4990

50-
## dev now
51-
```shell
52-
# start http server
53-
cd repocache
54-
PYTHONPATH=.. python main.py --debug --reload /tmp/packages
91+
curl http://127.0.0.1:5000/rust/rustup.sh | sh
5592
```
5693

94+
95+
## Settting file
96+
See [default.cfg](default.cfg)
97+
98+
99+
## Open source
57100
This repository was copy from pypicache early, but fully rewrite later.
58101
PR wellcome.

default.cfg

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ timeout = 120
44
retry = 3
55
user-agent = "Apache-Maven/3.6.0 (Java 1.8.0_202-release; Mac OS X 10.16)"
66

7+
78
[server]
89
address = 127.0.0.1:5000
910
cache-folder = /tmp/repocache
11+
SERVER_NAME = 192.168.1.2:5000
1012
# TODO: cache-404 = false
1113
# TODO: logging, debug, reload, process
1214

@@ -41,6 +43,12 @@ url = https://maven.dremio.com/free
4143
[mvn.upstream.dremio-public]
4244
url = https://maven.dremio.com/public
4345

46+
[mvn.upstream.confluent]
47+
url = http://packages.confluent.io/maven
48+
49+
[mvn.upstream.jitpack]
50+
url = https://jitpack.io
51+
4452
[mvn.upstream.redshift]
4553
url = https://s3.amazonaws.com/redshift-maven-repository/release
4654

@@ -54,3 +62,39 @@ retry = 10
5462
[mvn.upstream.local]
5563
# Without url mean: local repository
5664
# Place pom/jar files in /tmp/repocache/mvn/local
65+
66+
[npm.upstream.default]
67+
url = https://registry.npmjs.org
68+
69+
[npm.upstream.huaweicloud]
70+
url = https://mirrors.huaweicloud.com/repository/npm
71+
72+
# http://mirror.centos.org/centos/7/os/x86_64/Packages/
73+
[yum.upstream.aliyun]
74+
url = http://mirrors.aliyun.com/centos
75+
User-Agent = urlgrabber/3.9.1 yum/3.2.29
76+
# http://mirrors.aliyun.com/centos/6/readme | http://127.0.0.1:5000/centos/aliyun/----
77+
# https://mirrors.aliyun.com/repo/Centos-6.repo | http://127.0.0.1:5000/centos/aliyun/Centos-7.repo
78+
# https://mirrors.aliyun.com/repo/Centos-7.repo
79+
#
80+
# http://mirrors.aliyun.com/centos/6/os/x86_64/repodata/repomd.xml
81+
82+
# http://mirrors.huaweicloud.com/centos/7/atomic/x86_64/Packages/
83+
# http://mirrors.huaweicloud.com/centos/7/os/x86_64/repodata/repomd.xml
84+
# http://mirrors.huaweicloud.com/centos/7/atomic/x86_64/Packages/anaconda-21.48.22.121-3.rhelah.0.el7.centos.x86_64.rpm
85+
86+
[yum.upstream.huawei]
87+
url = http://mirrors.huaweicloud.com/centos
88+
User-Agent = urlgrabber/3.10 yum/3.4.3
89+
# http://mirrors.huaweicloud.com/centos/7/os/x86_64/repodata/repomd.xml
90+
# http://mirrors.huaweicloud.com/centos/6/os/x86_64/repodata/repomd.xml
91+
# /centos/huawei/6/os/x86_64/repodata/repomd.xml
92+
93+
[yum.upstream.sclo]
94+
url = http://mirrors.huaweicloud.com/centos/7.9.2009/sclo/x86_64/rh
95+
User-Agent = urlgrabber/3.10 yum/3.4.3
96+
# https://www.softwarecollections.org/en/scls/rhscl/rh-python36/
97+
# http://mirrorlist.centos.org/?arch=x86_64&release=7&repo=sclo-rh
98+
99+
[rust.upstream.default]
100+
url = https://static.rust-lang.org

repocache/main.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ def main():
2121
dest='verbose',
2222
action='store_true',
2323
help='Show additional command output.')
24-
parser.add_argument('--debug',
24+
parser.add_argument('-d,--debug',
2525
default=False,
26+
dest='debug',
2627
action='store_true',
2728
help='Turn on debugging logging and output.')
28-
parser.add_argument('--reload',
29+
parser.add_argument('-r,-reload',
2930
default=False,
31+
dest='reload',
3032
action='store_true',
3133
help='Turn on automatic reloading on code changes.')
3234
parser.add_argument('--processes',

repocache/maven.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22

33
from flask import Blueprint, make_response, render_template, request
4+
from flask.helpers import send_file
45
from tornado.util import ObjectDict
56
from werkzeug.exceptions import NotFound
67

@@ -20,23 +21,18 @@ class Maven(ModularView, Vendor):
2021
@expose('/<string:un>/<path:fullname>')
2122
def handle(self, un, fullname):
2223
'''un: maven repository name'''
23-
content = self._ensure(un, fullname)
24-
if content is None:
24+
f = self._ensure(un, fullname)
25+
if f is None:
2526
raise NotFound
2627

27-
# print(request.headers)
28-
'''fuck mvn GET with:
29-
Cache-Control: no-cache
30-
Cache-Store: no-store
31-
Pragma: no-cache'''
32-
33-
resp = make_response(content)
34-
resp.cache_control.max_age = 86400
35-
3628
if fullname.endswith('.pom') or fullname.endswith('.xml'):
37-
resp.headers['content-type'] = 'application/xml'
29+
mimetype = 'application/xml'
30+
elif fullname.endswith('.jar'):
31+
mimetype = 'application/java-archive'
32+
else:
33+
mimetype = 'application/octet-stream'
3834

39-
return resp
35+
return send_file(f, mimetype=mimetype)
4036

4137
def __init__(self, config):
4238
ModularView.__init__(

repocache/npm.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import json
2+
import logging
3+
4+
from flask import render_template, request, make_response, url_for
5+
from flask.helpers import send_file
6+
from tornado.util import ObjectDict
7+
from werkzeug.exceptions import NotFound
8+
9+
from repocache.modular_view import ModularView, expose
10+
from repocache.vendor import Vendor
11+
12+
logger = logging.getLogger(__name__)
13+
14+
15+
def create_upstream(name, section):
16+
'''create dict from section of ConfigParser'''
17+
tail = name[len('npm.upstream.'):]
18+
return ObjectDict(name=tail, **section)
19+
20+
21+
class NpmRepository(ModularView, Vendor):
22+
@expose("/")
23+
def index(self):
24+
'''TODO: list cached packages'''
25+
return self.upstreams
26+
27+
@expose("/<string:un>/<string:name>")
28+
def package(self, un, name):
29+
'''/smallest-png'''
30+
jd = self.ensure_package(un, name)
31+
if not jd:
32+
raise NotFound
33+
34+
return jd
35+
36+
@expose("/<string:un>/<string:name>/-/<string:filename>")
37+
def package_file(self, un, name, filename):
38+
'''smallest-png/-/smallest-png-2.0.0-2.tgz'''
39+
ud = self.upstreams.get(un)
40+
if ud is None:
41+
raise NotFound
42+
43+
jd = self.ensure_package(un, name)
44+
if not jd:
45+
raise NotFound
46+
47+
for v, vd in jd.get('versions').items():
48+
if vd.dist.tarball.endswith(filename):
49+
ud = ObjectDict(ud)
50+
del ud['url']
51+
52+
f = self.fetch_or_load_binary(
53+
f'npm/{un}/{name}/{filename}',
54+
fetch_handle=lambda: self.fetch(vd.dist._url, **ud),
55+
)
56+
return send_file(f, mimetype='application/octet-stream')
57+
58+
raise NotFound
59+
60+
@expose("/<string:un>/-/v1/search")
61+
def search(self, un):
62+
ud = self.upstreams.get(un)
63+
if ud is None:
64+
raise NotFound
65+
66+
resp = self.fetch(f'{ud.url}/-/v1/search', params=request.args, **ud)
67+
return resp.content
68+
69+
# -/npm/v1/security/audits/quick
70+
@expose("/<string:un>/-/<path:left>", methods=('POST',))
71+
def other(self, un, left):
72+
print('post:', request)
73+
return ''
74+
75+
def __init__(self, config):
76+
ModularView.__init__(
77+
self,
78+
name='npm',
79+
url_prefix='/npm',
80+
)
81+
82+
self.upstreams = {} # upstream name => Dict
83+
84+
for section_name in config:
85+
if section_name.startswith('npm.upstream.'):
86+
u = create_upstream(section_name, config[section_name])
87+
self.upstreams[u.name] = u
88+
89+
def _fetch(self, un, path):
90+
ud = self.upstreams.get(un)
91+
92+
if ud is None:
93+
raise NotFound
94+
95+
url = '{}/{}'.format(
96+
ud.url,
97+
path,
98+
)
99+
100+
ud = ObjectDict(ud)
101+
del ud['url']
102+
103+
return self.fetch(url, **ud)
104+
105+
def ensure_package(self, un, name):
106+
# TODO: local
107+
jd = self.fetch_or_load_json(
108+
f'npm/{un}/{name}.json',
109+
fetch_handle=lambda: self._fetch(un, name),
110+
)
111+
112+
# replace `dist.tarball` as local url
113+
for v, vd in jd.get('versions').items():
114+
# if un in
115+
ud = self.upstreams.get(un)
116+
prefix = f'{ud.url}/{name}/-/'
117+
pos = vd.dist.tarball.find(prefix)
118+
if pos == 0:
119+
filename = vd.dist.tarball[pos + len(prefix):]
120+
vd.dist._url = vd.dist.tarball
121+
vd.dist.tarball = url_for(
122+
'npm.package_file',
123+
un=un,
124+
name=name,
125+
filename=filename,
126+
_external=True,
127+
)
128+
return jd

0 commit comments

Comments
 (0)