summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xgit-mirror34
-rwxr-xr-xgit-mirror-gitlab-ce56
-rwxr-xr-xgit-mirror-gitlab-ee32
-rw-r--r--git-mirror.conf.example5
-rw-r--r--libremessages.rb3
5 files changed, 89 insertions, 41 deletions
diff --git a/git-mirror b/git-mirror
index 113379a..6fc6ebb 100755
--- a/git-mirror
+++ b/git-mirror
@@ -1,12 +1,10 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Copyright © 2014, 2016 Luke Shumaker <lukeshu@sbcglobal.net>
#
# This work is free. You can redistribute it and/or modify it under the
# terms of the Do What The Fuck You Want To Public License, Version 2,
# as published by Sam Hocevar. See the COPYING file for more details.
-# Depends 4.4+, as it uses the '-d' flag to 'mapfile'.
-#
# Depends on the 'gitget' and 'libremessages' commands. On Parabola
# GNU/Linux-libre, those are the 'gitget' and 'librelib' packages,
# respectively.
@@ -67,13 +65,14 @@ download() {
local remote=${_remote%%#*}
local params=(${_remote#"$remote"})
+ msg 'Downloading %s <- %s' "$repo" "${remote%%#*}"
+
# download the repository
local url
-
url="$(remote "$remote" pull-url)"
gitget -f -n "$repo" bare "$url" "$local"
+
# download the metadata
- msg2 "Fetching metadata for repo '%s'" "$repo"
get-meta "$remote" > "$local/git-mirror.tmp"
git config --file "$local/config" --rename-section git-mirror git-mirror-bak 2>/dev/null || true
local IFS='='
@@ -90,16 +89,19 @@ upload() (
local local=$2
local remote=$3
+ msg 'Uploading %s -> %s' "$repo" "${remote%%#*}"
+
# push metadata
- msg2 "Pushing metadata for repo '%s'" "$repo"
local meta
- mapfile -d '' meta < <(git config --file "$local/config" -z --get-regexp '^git-mirror[.]'|sed -z 's/ /=/')
+ mapfile meta < <(git config --file "$local/config" --list|sed -n 's/^git-mirror[.]//p')
+ meta=("${meta[@]%$'\n'}")
set-meta "$remote" "${meta[@]}"
+
# push repository
- msg2 "Pushing repo '%s'" "repo"
local repo_mode
repo_mode=$(remote "$remote" repo-mode)
if [[ $repo_mode == passive ]]; then
+ msg2 "Pushing repo %s" "$repo"
local push_url
push_url="$(remote "$remote" push-url)"
cd "$local" && git push --mirror "$push_url"
@@ -108,11 +110,9 @@ upload() (
get-meta() (
[[ $# = 1 ]] || panic
- local _remote=$1
-
- local IFS='&'
- local remote=${_remote%%#*}
- local params=(${_remote#"$remote"})
+ local IFS remote _params params
+ IFS='#' read remote _params <<<"$1"
+ IFS='&' read -a params <<<"$_params"
remote "$remote" get-meta
[[ ${#params[@]} = 0 ]] || printf '%s\n' "${params[@]}"
@@ -120,13 +120,11 @@ get-meta() (
set-meta() {
[[ $# -ge 1 ]] || panic
- local _remote=$1
+ local IFS remote _params params
+ IFS='#' read remote _params <<<"$1"
+ IFS='&' read -a params <<<"$_params"
local args=("${@:2}")
- local IFS='&'
- local remote=${_remote%%#*}
- local params=(${_remote#"$remote"})
-
remote "$remote" set-meta "${args[@]}" "${params[@]}"
}
diff --git a/git-mirror-gitlab-ce b/git-mirror-gitlab-ce
index 1c628e8..ed45aec 100755
--- a/git-mirror-gitlab-ce
+++ b/git-mirror-gitlab-ce
@@ -4,6 +4,7 @@
# TODO: add 'owner' to get/set_meta
load 'git-mirror-backend.rb'
+load 'libremessages.rb'
require 'net/http'
require 'uri'
require 'cgi'
@@ -17,6 +18,9 @@ class GitLabCE < GitMirrorBackend
def obj
return @obj
end
+ def to_s
+ return @obj.to_s
+ end
end
def initialize()
@@ -82,24 +86,30 @@ class GitLabCE < GitMirrorBackend
end
def get_meta
- return self.info.select{|k,v| @vars.include?(k.to_sym)}
+ return self.info.select{|k,v| @gl.vars.include?(k.to_sym)}
end
def set_meta(map)
mirror = map["mirror"]
map.delete("mirror")
- illegal = map.select{|k,v| not @vars.include?(k.to_sym)}
+ illegal = map.select{|k,v| not @gl.vars.include?(k.to_sym)}
if illegal.count > 0
raise Error.new(illegal)
end
- if info == nil
+ if self.info().nil?
# create
- req = Net::HTTP::Put.new(@gl.config['apiurl'] + "projects")
+ libremessages('msg2', 'Creating repo %s', @project_id)
+ namespace, path = @project_id.split('/', 2)
+ namespace_id = namespace_path2id(namespace)
+
+ req = Net::HTTP::Post.new(@gl.config['apiurl'] + "projects")
req.add_field("PRIVATE-TOKEN", @gl.config['apikey'])
req.add_field("Content-Type", "application/json")
- map["path"] = @project_id
+ map["name"] ||= path
+ map["namespace_id"] = namespace_id
+ map["path"] = path
if not mirror.nil?
map["import_url"] = mirror
end
@@ -108,10 +118,11 @@ class GitLabCE < GitMirrorBackend
if res.code != "201"
raise Error.new(res)
end
- info = JSON::parse(res.body)
+ self.info = JSON::parse(res.body)
else
# update
- req = Net::HTTP::Put.new(@gl.config['apiurl'] + "projects/" + CGI::escape(info["id"].to_s))
+ libremessages('msg2', 'Updating repo %s metadata', @project_id)
+ req = Net::HTTP::Put.new(@gl.config['apiurl'] + "projects/" + CGI::escape(self.info["id"].to_s))
req.add_field("PRIVATE-TOKEN", @gl.config['apikey'])
req.add_field("Content-Type", "application/json")
req.body = JSON::dump(map)
@@ -119,7 +130,26 @@ class GitLabCE < GitMirrorBackend
if res.code != "200"
raise Error.new(res)
end
- info = JSON::parse(res.body)
+ self.info = JSON::parse(res.body)
+ end
+ return nil
+ end
+
+ def namespace_path2id(path, pageno=1)
+ req = Net::HTTP::Get.new(@gl.config['apiurl'] + "namespaces?page=#{pageno}&search=#{CGI::escape(path)}")
+ req.add_field("PRIVATE-TOKEN", @gl.config['apikey'])
+ res = @gl.connection(req.uri).request(req)
+ if res.code != "200"
+ raise Error.new(res)
+ end
+ page = JSON::parse(res.body)
+ page.each do |namespace|
+ if namespace["path"] == path
+ return namespace["id"].to_i
+ end
+ end
+ if pageno < res['X-Total-Pages'].to_i
+ return namespace_path2id(path, pageno+1)
end
return nil
end
@@ -159,9 +189,13 @@ class GitLabCE < GitMirrorBackend
def cmd_set_meta(project_id, *pairs)
map = {}
pairs.each do |pair|
- key, val = arg.split('=', 2)
+ key, val = pair.split('=', 2)
key = key.gsub('-', '_')
- map[key] = val
+ if val.nil?
+ map.delete(key)
+ else
+ map[key] = val
+ end
end
self.project(project_id).set_meta(map)
return nil
@@ -176,7 +210,7 @@ class GitLabCE < GitMirrorBackend
end
def cmd_repo_mode(project_id)
- return self.project(projecT_id).repo_mode()
+ return self.project(project_id).repo_mode()
end
def vars
diff --git a/git-mirror-gitlab-ee b/git-mirror-gitlab-ee
index 394a5f7..425bb48 100755
--- a/git-mirror-gitlab-ee
+++ b/git-mirror-gitlab-ee
@@ -29,17 +29,17 @@ class GitLabEE < GitLabCE
class Project < GitLabCE::Project
def mirrorURL
unless @cache.has_key?(:mirror)
- req = Net::HTTP::Get.new(URI(_info["web_url"]+"/mirror"))
- req.add_field("PRIVATE-TOKEN", @api_key)
+ req = Net::HTTP::Get.new(URI(self.info["web_url"]+"/mirror"))
+ req.add_field("PRIVATE-TOKEN", @gl.config['apikey'])
res = @gl.connection(req.uri).request(req)
if res.code != "200"
throw res
end
- @cache[:mirror_res]=res
+
doc = Nokogiri::HTML(res.body)
- @cache[:mirror_cookie] = res["set-cookie"]
- @cache[:mirror_token] = doc.css('input[name="authenticity_token"]').first["value"]
+ @cache[:session] = res["set-cookie"]
+ @cache[:mirror_transaction] = doc.css('input[name="authenticity_token"]').first["value"]
is_mirror = doc.css("#project_mirror").first["checked"]
if !is_mirror
@cache[:mirror] = nil
@@ -51,26 +51,27 @@ class GitLabEE < GitLabCE
end
def mirrorURL=(url)
+ libremessages('msg2', 'Setting mirror URL for %s', @project_id)
self.mirrorURL()
req = Net::HTTP::Patch.new(URI(self.info["web_url"]+"/mirror"))
req.add_field("PRIVATE-TOKEN", @gl.config['apikey']) # authenticate
- req.add_field("Cookie", @cache[:mirror_cookie]) # session id
+ req.add_field("Cookie", @cache[:session]) # session id
req.form_data = {
"utf8" => "✓",
- "authenticity_token" => @cache[:mirror_token], # session state
+ "authenticity_token" => @cache[:mirror_transaction], # session state
"project[mirror]" => (url.nil? ? "0" : "1"),
"project[import_url]" => url.to_s,
+ "project[mirror_user_id]" => @gl.user_id,
}
-
res = @gl.connection(req.uri).request(req)
if res.code != "302"
throw res
end
@cache.delete(:mirror)
- @cache.delete(:mirror_token)
- @cache.delete(:mirror_cookie)
+ @cache.delete(:mirror_transaction)
+ @cache.delete(:session)
return URI(url)
end
@@ -96,6 +97,17 @@ class GitLabEE < GitLabCE
return (self.mirrorURL.nil? ? "passive" : "active")
end
end
+
+ def user_id
+ req = Net::HTTP::Get.new(self.config['apiurl'] + 'user')
+ req.add_field("PRIVATE-TOKEN", self.config['apikey'])
+ res = self.connection(req.uri).request(req)
+ if res.code != "200"
+ raise Error.new(res)
+ end
+ user = JSON::parse(res.body)
+ return user["id"]
+ end
end
if __FILE__ == $0
diff --git a/git-mirror.conf.example b/git-mirror.conf.example
index 722f00d..c3fd523 100644
--- a/git-mirror.conf.example
+++ b/git-mirror.conf.example
@@ -22,5 +22,6 @@
[repo "abslibre/abslibre"]
upstream = parabola:abslibre/abslibre.git
local = abslibre/abslibre.git
- downstream = gitlab:parabola/abslibre_abslibre#mirror=https://git.parabola.nu/abslibre/abslibre.git&name=abslibre╱abslibre
- downstream = github:parabola/abslibre_abslibre
+ downstream = gitlab:parabola/abslibre_abslibre#mirror=https://git.parabola.nu/abslibre/abslibre.git&name=abslibre╱abslibre
+ #downstream = github:parabola/abslibre_abslibre
+#∼lukeshu╱systemd
diff --git a/libremessages.rb b/libremessages.rb
new file mode 100644
index 0000000..4247a1e
--- /dev/null
+++ b/libremessages.rb
@@ -0,0 +1,3 @@
+def libremessages(*args)
+ Process.wait(fork{exec('libremessages', *args)})
+end