From 6208964ad32a7f36e03d8d14d969642255524566 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 15 Dec 2016 18:23:32 -0500 Subject: fix --- git-mirror | 34 ++++++++++++++---------------- git-mirror-gitlab-ce | 56 +++++++++++++++++++++++++++++++++++++++---------- git-mirror-gitlab-ee | 32 +++++++++++++++++++--------- git-mirror.conf.example | 5 +++-- libremessages.rb | 3 +++ 5 files changed, 89 insertions(+), 41 deletions(-) create mode 100644 libremessages.rb 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 # # 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 -- cgit v1.2.3-54-g00ecf