-
Notifications
You must be signed in to change notification settings - Fork 1
/
lektor_git_src_publisher.py
147 lines (110 loc) · 4.38 KB
/
lektor_git_src_publisher.py
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
140
141
142
143
144
145
146
147
# -*- coding: utf-8 -*-
from lektor.pluginsystem import Plugin
from lektor.publisher import Publisher, _patch_git_env
import os
import subprocess
class GitSrcPublisher(Publisher):
"""
Helper class to simplify the useful publishers.
"""
def _git(self, args, **kwargs):
"""
Run a git command and return a Command object.
This comes (mostly) from lektor.publisher.GithubPagesPublisher.
"""
root_path = self.env.root_path
kwargs["env"] = _patch_git_env(kwargs.pop("env", None), None)
kwargs["stdout"] = subprocess.PIPE
kwargs["universal_newlines"] = True
kwargs["bufsize"] = 1
git_cmd = ["git"]
# This might help mitigate an issue while running under Docker
if root_path != os.getcwd():
# This is important because lektor might be running with --project
git_cmd.extend(["-C", root_path])
git_cmd.extend(args)
return subprocess.run(git_cmd, **kwargs)
def _git_output(self, args, **kwargs):
"""
Run a git Command but return just its output.
"""
return self._git(args, **kwargs).stdout
def branch(self, target_url):
return target_url[1].strip()
def remote(self):
"""
Return the configured remote.
"""
return self._git_output(["remote"]).strip()
def current_branch(self):
"""
Return the current branch.
"""
return self._git_output(["rev-parse", "--abbrev-ref", "HEAD"]).strip()
def is_in_branch(self, target_url):
"""
Return True if the current branch matches the target branch,
or False otherwise.
"""
current = self.current_branch()
target = self.branch(target_url)
return current == target
class GitSrcForcePullPublisher(GitSrcPublisher):
"""
Simple publisher that pulls external source changes.
It may cause data loss if the branch can't be pulled cleanly, in which
case the current directory will be forcibly cleaned and remote data will
be pulled.
Use with a publisher in your .lektorproject file with target:
gitsrc-forcepull://BRANCH
This will use the default remote and assumes credentials are a
solved problem, in particular the credentials argument is ignored.
"""
def publish(self, target_url, credentials=None, **extra):
yield "Fetching updates...\n"
yield self._git_output(["fetch", "--progress"])
yield "Saving any uncommitted changes...\n"
yield self._git_output(["stash"])
if not self.is_in_branch(target_url):
yield "Changing branch as requested...\n"
yield self._git_output(
[
"checkout",
"-b",
self.branch(target_url),
"-t",
self.remote() + "/" + self.branch(target_url),
]
)
yield "Merging remote changes...\n"
yield self._git_output(
["merge", "--strategy=recursive", "--strategy-option=theirs"]
)
yield "Restore any previously uncommitted changes...\n"
yield self._git_output(["stash", "pop"])
yield "\nDone!"
class GitSrcPushPublisher(GitSrcPublisher):
"""
Simple publisher that pushes local source changes.
It is recommended that any changes start by "publishing" to a
gitsrc-forcepull target.
Use with a publisher in your .lektorproject file with target:
gitsrc-push://BRANCH
This will use the default remote and assumes credentials are a
solved problem, in particular the credentials argument is ignored.
"""
def publish(self, target_url, credentials=None, **extra):
yield "Staging changes"
yield self._git_output(["add", "."])
yield "Commiting changes"
yield self._git_output(["commit", "-m", "Updated from Lektor"])
yield "Pushing changes"
yield self._git_output(["push", self.remote(), self.branch(target_url)])
yield "\nDone!"
class GitSrcPublisherPlugin(Plugin):
name = "git-src-publisher"
description = u"Simple plugin to use Lektor to abstract away git usage."
def on_setup_env(self, **extra):
# Register publishers
self.env.add_publisher("gitsrc-forcepull", GitSrcForcePullPublisher)
self.env.add_publisher("gitsrc-push", GitSrcPushPublisher)