File: remote.go

package info (click to toggle)
golang-github-sjoerdsimons-ostree-go 0.0~git20180830.1ac74ff-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 308 kB
  • sloc: ansic: 173; makefile: 4
file content (139 lines) | stat: -rw-r--r-- 2,956 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package otbuiltin

import (
	"bytes"
	"fmt"
	glib "github.com/sjoerdsimons/ostree-go/pkg/glibobject"
	"reflect"
	"strings"
	"unicode"
	"unsafe"
)

// #cgo pkg-config: ostree-1
// #include <stdlib.h>
// #include <glib.h>
// #include <ostree.h>
// #include "builtin.go.h"
import "C"

type RemoteOptions struct {
	ContentUrl          string "contenturl"
	Proxy               string
	NoGpgVerify         bool "gpg-verify, invert"
	NoGpgVerifySummary  bool "gpg-verify-summary, invert"
	TlsPermissive       bool
	TlsClientCertPath   string
	TlsClientKeyPath    string
	TlsCaPath           string
	UnconfiguredState   string
	MinFreeSpacePercent string
}

func toDashString(in string) string {
	var out bytes.Buffer
	for i, c := range in {
		if !unicode.IsUpper(c) {
			out.WriteRune(c)
			continue
		}

		if i > 0 {
			out.WriteString("-")
		}
		out.WriteRune(unicode.ToLower(c))
	}

	return out.String()
}

func optionsToVariant(options RemoteOptions) *C.GVariant {
	casv := C.CString("a{sv}")
	defer C.free(unsafe.Pointer(casv))
	csv := C.CString("{sv}")
	defer C.free(unsafe.Pointer(csv))

	builder := C.g_variant_builder_new(C._g_variant_type(casv))

	v := reflect.ValueOf(options)
	t := v.Type()
	for i := 0; i < v.NumField(); i++ {
		vf := v.Field(i)
		tf := t.Field(i)
		invert := false

		name := toDashString(tf.Name)
		if tf.Tag != "" {
			opts := strings.Split(string(tf.Tag), ",")
			if opts[0] != "" {
				name = opts[0]
			}
			for _, o := range opts[1:] {
				switch strings.TrimSpace(o) {
				case "invert":
					invert = true
				default:
					panic(fmt.Sprintf("Unhandled flag: %s", o))
				}
			}
		}

		var variant *C.GVariant
		switch vf.Kind() {
		case reflect.Bool:
			/* Should probalby use e.g. Maybe type so it can judge unitialized */
			b := vf.Bool()
			var cb C.gboolean

			if !b {
				// Still the default, so don't bother setting it
				continue
			}
			if invert {
				cb = C.gboolean(0)
			} else {
				cb = C.gboolean(1)
			}
			variant = C.g_variant_new_boolean(cb)
		case reflect.String:
			if vf.String() == "" {
				continue
			}
			variant = C.g_variant_new_take_string((*C.gchar)(C.CString(vf.String())))
		default:
			panic(fmt.Sprintf("Can't handle type of field: %s", tf.Name))
		}

		cname := C.CString(name)
		defer C.free(unsafe.Pointer(cname))
		C._g_variant_builder_add_twoargs(builder, csv, cname, variant)
	}

	coptions := C.g_variant_builder_end(builder)
	return coptions
}

func (repo *Repo) RemoteAdd(name, url string, options RemoteOptions,
	cancellable *glib.GCancellable) error {

	var cerr *C.GError = nil

	cname := C.CString(name)
	defer C.free(unsafe.Pointer(cname))

	curl := C.CString(url)
	defer C.free(unsafe.Pointer(curl))

	coptions := optionsToVariant(options)
	C.g_variant_ref_sink(coptions)

	r := C.ostree_repo_remote_add(repo.native(), cname, curl, coptions, cCancellable(cancellable), &cerr)

	C.g_variant_unref(coptions)

	if !gobool(r) {
		return generateError(cerr)
	}

	return nil
}