]> git.pld-linux.org Git - packages/xpra.git/blob - xpra.spec
Release 5 (by relup.sh)
[packages/xpra.git] / xpra.spec
1 # TODO
2 # - test and finish systemd integration
3 # - subpackages for client/server, see http://xpra.org/dev.html
4 # - nvenc>=7 for cuda support (on bcond)
5 # - nvfbc (on bcond)
6 #
7 # Conditional build:
8 %bcond_without  client          # client part
9 %bcond_without  server          # server part
10 %bcond_without  sound           # (gstreamer) sound support
11 %bcond_without  clipboard       # clipboard support
12 %bcond_without  swscale         # swscale colorspace conversion support
13 %bcond_without  opengl          # OpenGL support
14 %bcond_without  ffmpeg          # avcodec decoding / FFmpeg encoding support
15 %bcond_without  vpx             # VPX/WebM support
16 %bcond_without  webp            # WebP support
17 %bcond_without  x264            # x264 encoding
18 %bcond_without  x265            # x265 encoding
19
20 %ifarch i386 i486 x32
21 %undefine       with_x265
22 %endif
23
24 Summary:        Xpra gives you "persistent remote applications" for X
25 Summary(pl.UTF-8):      Xpra - "stałe zdalne aplikacje" dla X
26 Name:           xpra
27 Version:        2.5.3
28 Release:        5
29 License:        GPL v2+
30 Group:          X11/Applications/Networking
31 Source0:        http://xpra.org/src/%{name}-%{version}.tar.xz
32 # Source0-md5:  2fac9c558c099a6ea13d0202732bd684
33 Patch0:         setup-cc-ccache.patch
34 Patch1:         %{name}-libexecdir.patch
35 Patch2:         python3-version.patch
36 URL:            http://xpra.org/
37 BuildRequires:  OpenGL-devel
38 # libavcodec >= 57 for dec_avcodec, libavcodec >= 58.18 for enc_ffmpeg, libswscale
39 %{?with_ffmpeg:BuildRequires:   ffmpeg-devel >= 3.4}
40 BuildRequires:  gtk+3-devel >= 3.0
41 BuildRequires:  libjpeg-turbo-devel >= 1.4
42 BuildRequires:  libvpx-devel >= 1.4
43 BuildRequires:  libwebp-devel >= 0.5
44 %{?with_x264:BuildRequires:     libx264-devel}
45 %{?with_x265:BuildRequires:     libx265-devel}
46 BuildRequires:  libyuv-devel
47 BuildRequires:  pam-devel
48 BuildRequires:  pkgconfig
49 BuildRequires:  python3-Cython >= 0.20
50 BuildRequires:  python3-devel >= 1:3.4
51 BuildRequires:  python3-pycairo-devel
52 BuildRequires:  python3-pygobject3-devel >= 3.0
53 BuildRequires:  python3-setuptools
54 BuildRequires:  rpm-pythonprov
55 BuildRequires:  sed >= 4.0
56 BuildRequires:  systemd-devel >= 1:209
57 BuildRequires:  tar >= 1:1.22
58 BuildRequires:  xorg-lib-libX11-devel
59 BuildRequires:  xorg-lib-libXcomposite-devel
60 BuildRequires:  xorg-lib-libXdamage-devel
61 BuildRequires:  xorg-lib-libXext-devel
62 BuildRequires:  xorg-lib-libXfixes-devel
63 BuildRequires:  xorg-lib-libXi-devel
64 BuildRequires:  xorg-lib-libXrandr-devel
65 BuildRequires:  xorg-lib-libXtst-devel
66 BuildRequires:  xorg-lib-libxkbfile-devel
67 BuildRequires:  xz
68 Requires:       gdk-pixbuf2 >= 2.0
69 Requires:       glib2 >= 2.0
70 Requires:       gobject-introspection >= 1
71 Requires:       gtk+3 >= 3.0
72 Requires:       libjpeg-turbo >= 1.4
73 Requires:       libvpx >= 1.4
74 Requires:       libwebp >= 0.5
75 Requires:       python3-pycairo
76 Requires:       python3-pygobject3 >= 3.0
77 Requires:       xorg-app-setxkbmap
78 Requires:       xorg-app-xauth
79 Requires:       xorg-app-xmodmap
80 Requires:       xorg-xserver-Xvfb
81 Suggests:       python3-PIL
82 Suggests:       python3-PyOpenGL
83 Suggests:       python3-numpy
84 BuildRoot:      %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
85
86 # currently lib, not %{_lib} (see cups.spec)
87 %define         cupsdir         /usr/lib/cups/backend
88 # xpra/x11/bindings/randr_bindings.c:... error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
89 %define         specflags       -fno-strict-aliasing
90
91 %description
92 Xpra gives you "persistent remote applications" for X. That is, unlike
93 normal X applications, applications run with xpra are "persistent" --
94 you can run them remotely, and they don't die if your connection does.
95 You can detach them, and reattach them later -- even from another
96 computer -- with no loss of state. And unlike VNC or RDP, xpra is for
97 remote applications, not remote desktops -- individual applications
98 show up as individual windows on your screen, managed by your window
99 manager. They're not trapped in a box.
100
101 So basically it's screen for remote X apps.
102
103 %description -l pl.UTF-8
104 Xpra daje "stałe zdalne aplikacje" dla serwera X, które w
105 przeciwieństwie do zwykłych X-owych aplikacji, uruchamiane są z xprą
106 jako niezamykające. Można je uruchomić zdalnie i one nie zostaną
107 zamknięte, gdy połączenie zostanie przerwane. Można je odłączyć i
108 podłączyć z powrotem później, również z innego komputera, bez straty
109 stanu. W odróżnieniu od VNC czy RDP, xpra jest dla zdalnych aplikacji,
110 a nie zdalnych pulpitów - pojedyncze aplikacje pokazują się jako
111 samodzielne okno na lokalnym ekranie, zarządzane przez lokalnego
112 zarządcę okien.
113
114 W uproszczeniu xpra to "screen" dla zdalnych aplikacji X-owych.
115
116 %package -n cups-backend-xpra
117 Summary:        Xpra backend for CUPS
118 Summary(pl.UTF-8):      Backend Xpra dla CUPS-a
119 Group:          Applications/Printing
120 Requires:       %{name} = %{version}-%{release}
121 Requires:       cups
122
123 %description -n cups-backend-xpra
124 Xpra backend for CUPS.
125
126 %description -n cups-backend-xpra -l pl.UTF-8
127 Backend Xpra dla CUPS-a.
128
129 %prep
130 %setup -q
131 %patch0 -p1
132 %patch1 -p1
133 %patch2 -p1
134
135 %{__sed} -i -e '1s,/usr/bin/env python$,%{__python3},' cups/xpraforwarder $(grep -l '/usr/bin/env python' -r xpra scripts)
136 %{__sed} -i -e 's,"/bin/xpra_udev_product_version","%{_bindir}/xpra_udev_product_version",' udev/rules.d/71-xpra-virtual-pointer.rules
137 %{__sed} -i -e 's,@libexec@,%{_libexecdir},' setup.py
138
139 %define setup_opts \\\
140         --with-PIC \\\
141         --with-Xdummy \\\
142         --with-Xdummy_wrapper \\\
143         %{__with_without client} \\\
144         %{__with_without clipboard} \\\
145         %{__with_without swscale csc_swscale} \\\
146         --with%{!?debug:out}-debug \\\
147         %{__with_without ffmpeg dec_avcodec2} \\\
148         %{__with_without ffmpeg enc_ffmpeg} \\\
149         %{__with_without x264 enc_x264} \\\
150         %{__with_without x265 enc_x265} \\\
151         --without-gtk2 \\\
152         --with-gtk3 \\\
153         --without-nvenc \\\
154         --without-nvfbc \\\
155         %{__with_without opengl} \\\
156         %{__with_without server} \\\
157         %{__with_without server shadow} \\\
158         %{__with_without sound} \\\
159         --without-strict \\\
160         %{__with_without vpx} \\\
161         --with-warn \\\
162         %{__with_without webp} \\\
163         --with-x11 \\\
164         %{nil}
165
166 %build
167 CC="%{__cc}" \
168 CFLAGS="%{rpmcflags}" \
169 %{__python3} setup.py build \
170         %{setup_opts}
171
172 %install
173 rm -rf $RPM_BUILD_ROOT
174
175 %{__python3} setup.py install \
176         %{setup_opts} \
177         --skip-build \
178         --prefix=%{_prefix} \
179         --install-purelib=%{py3_sitescriptdir} \
180         --install-platlib=%{py3_sitedir} \
181         --optimize=2 \
182         --root=$RPM_BUILD_ROOT
183
184 %{__rm} $RPM_BUILD_ROOT%{_datadir}/xpra/COPYING
185 %{__rm} $RPM_BUILD_ROOT%{_datadir}/xpra/README
186
187 install -d $RPM_BUILD_ROOT/lib/udev/rules.d
188 %{__mv} $RPM_BUILD_ROOT{%{_prefix},}/lib/udev/rules.d/71-xpra-virtual-pointer.rules
189
190 %py_postclean
191
192 %clean
193 rm -rf $RPM_BUILD_ROOT
194
195 %files
196 %defattr(644,root,root,755)
197 %doc NEWS README
198 %dir %{_sysconfdir}/%{name}
199 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/xorg.conf
200 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/xpra.conf
201 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/xorg-uinput.conf
202 %dir %{_sysconfdir}/%{name}/conf.d
203 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/05_features.conf
204 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/10_network.conf
205 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/12_ssl.conf
206 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/15_file_transfers.conf
207 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/16_printing.conf
208 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/20_sound.conf
209 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/30_picture.conf
210 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/35_webcam.conf
211 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/40_client.conf
212 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/42_client_keyboard.conf
213 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/50_server_network.conf
214 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/55_server_x11.conf
215 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/60_server.conf
216 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/conf.d/65_proxy.conf
217 %config(noreplace) %verify(not md5 mtime size) /etc/sysconfig/xpra
218 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/X11/xorg.conf.d/90-xpra-virtual.conf
219 %config(noreplace) %verify(not md5 mtime size) /etc/pam.d/xpra
220 /etc/dbus-1/system.d/xpra.conf
221 %{systemdunitdir}/xpra.service
222 %{systemdunitdir}/xpra.socket
223 /usr/lib/sysusers.d/xpra.conf
224 /lib/udev/rules.d/71-xpra-virtual-pointer.rules
225 %attr(755,root,root) %{_bindir}/xpra
226 %attr(755,root,root) %{_bindir}/xpra_Xdummy
227 %attr(755,root,root) %{_bindir}/xpra_launcher
228 %attr(755,root,root) %{_bindir}/xpra_signal_listener
229 %attr(755,root,root) %{_bindir}/xpra_udev_product_version
230 %dir %{_libexecdir}/xpra
231 %attr(755,root,root) %{_libexecdir}/xpra/auth_dialog
232 %attr(755,root,root) %{_libexecdir}/xpra/gnome-open
233 %attr(755,root,root) %{_libexecdir}/xpra/gvfs-open
234 %attr(755,root,root) %{_libexecdir}/xpra/xdg-open
235 %{_datadir}/appdata/xpra.appdata.xml
236 %{_datadir}/mime/packages/application-x-xpraconfig.xml
237 %{_datadir}/xpra
238 %{_desktopdir}/xpra.desktop
239 %{_desktopdir}/xpra-gui.desktop
240 %{_desktopdir}/xpra-launcher.desktop
241 %{_desktopdir}/xpra-shadow.desktop
242 %{_iconsdir}/xpra.png
243 %{_iconsdir}/xpra-mdns.png
244 %{_iconsdir}/xpra-shadow.png
245 %{systemdtmpfilesdir}/xpra.conf
246 # specified in the above (xpra group seems to be optional though)
247 #%attr(770,root,xpra) %dir /run/xpra
248 %{_mandir}/man1/xpra.1*
249 %{_mandir}/man1/xpra_launcher.1*
250
251 %dir %{py3_sitedir}/xpra
252 %dir %{py3_sitedir}/xpra/buffers
253 %{py3_sitedir}/xpra/buffers/*.py
254 %{py3_sitedir}/xpra/buffers/__pycache__
255 %attr(755,root,root) %{py3_sitedir}/xpra/buffers/membuf.cpython-*.so
256 %dir %{py3_sitedir}/xpra/client
257 %{py3_sitedir}/xpra/client/gl
258 %dir %{py3_sitedir}/xpra/client/gtk3
259 %attr(755,root,root) %{py3_sitedir}/xpra/client/gtk3/cairo_workaround.cpython-*.so
260 %{py3_sitedir}/xpra/client/gtk3/*.py
261 %{py3_sitedir}/xpra/client/gtk3/__pycache__
262 %{py3_sitedir}/xpra/client/gtk_base
263 %{py3_sitedir}/xpra/client/mixins
264 %{py3_sitedir}/xpra/client/*.py
265 %{py3_sitedir}/xpra/client/__pycache__
266 %{py3_sitedir}/xpra/clipboard
267 %dir %{py3_sitedir}/xpra/codecs
268 %dir %{py3_sitedir}/xpra/codecs/argb
269 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/argb/argb.cpython-*.so
270 %{py3_sitedir}/xpra/codecs/argb/*.py
271 %{py3_sitedir}/xpra/codecs/argb/__pycache__
272 %dir %{py3_sitedir}/xpra/codecs/csc_libyuv
273 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/csc_libyuv/colorspace_converter.cpython-*.so
274 %{py3_sitedir}/xpra/codecs/csc_libyuv/*.py
275 %{py3_sitedir}/xpra/codecs/csc_libyuv/__pycache__
276 %if %{with swscale}
277 %dir %{py3_sitedir}/xpra/codecs/csc_swscale
278 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/csc_swscale/colorspace_converter.cpython-*.so
279 %{py3_sitedir}/xpra/codecs/csc_swscale/*.py
280 %{py3_sitedir}/xpra/codecs/csc_swscale/__pycache__
281 %endif
282 %if %{with ffmpeg}
283 %dir %{py3_sitedir}/xpra/codecs/dec_avcodec2
284 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/dec_avcodec2/decoder.cpython-*.so
285 %{py3_sitedir}/xpra/codecs/dec_avcodec2/*.py
286 %{py3_sitedir}/xpra/codecs/dec_avcodec2/__pycache__
287 %endif
288 %if %{with ffmpeg}
289 %dir %{py3_sitedir}/xpra/codecs/enc_ffmpeg
290 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/enc_ffmpeg/encoder.cpython-*.so
291 %{py3_sitedir}/xpra/codecs/enc_ffmpeg/*.py
292 %{py3_sitedir}/xpra/codecs/enc_ffmpeg/__pycache__
293 %endif
294 %{py3_sitedir}/xpra/codecs/enc_proxy
295 %if %{with x264}
296 %dir %{py3_sitedir}/xpra/codecs/enc_x264
297 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/enc_x264/encoder.cpython-*.so
298 %{py3_sitedir}/xpra/codecs/enc_x264/*.py
299 %{py3_sitedir}/xpra/codecs/enc_x264/__pycache__
300 %endif
301 %if %{with x265}
302 %dir %{py3_sitedir}/xpra/codecs/enc_x265
303 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/enc_x265/encoder.cpython-*.so
304 %{py3_sitedir}/xpra/codecs/enc_x265/*.py
305 %{py3_sitedir}/xpra/codecs/enc_x265/__pycache__
306 %endif
307 %dir %{py3_sitedir}/xpra/codecs/jpeg
308 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/jpeg/decoder.cpython-*.so
309 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/jpeg/encoder.cpython-*.so
310 %{py3_sitedir}/xpra/codecs/jpeg/*.py
311 %{py3_sitedir}/xpra/codecs/jpeg/__pycache__
312 %dir %{py3_sitedir}/xpra/codecs/libav_common
313 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/libav_common/av_log.cpython-*.so
314 %{py3_sitedir}/xpra/codecs/libav_common/*.py
315 %{py3_sitedir}/xpra/codecs/libav_common/__pycache__
316 %{py3_sitedir}/xpra/codecs/pillow
317 %dir %{py3_sitedir}/xpra/codecs/v4l2
318 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/v4l2/pusher.cpython-*.so
319 %{py3_sitedir}/xpra/codecs/v4l2/*.py
320 %{py3_sitedir}/xpra/codecs/v4l2/__pycache__
321 %dir %{py3_sitedir}/xpra/codecs/vpx
322 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/vpx/decoder.cpython-*.so
323 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/vpx/encoder.cpython-*.so
324 %{py3_sitedir}/xpra/codecs/vpx/*.py
325 %{py3_sitedir}/xpra/codecs/vpx/__pycache__
326 %dir %{py3_sitedir}/xpra/codecs/webp
327 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/webp/decode.cpython-*.so
328 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/webp/encode.cpython-*.so
329 %{py3_sitedir}/xpra/codecs/webp/*.py
330 %{py3_sitedir}/xpra/codecs/webp/__pycache__
331 %dir %{py3_sitedir}/xpra/codecs/xor
332 %attr(755,root,root) %{py3_sitedir}/xpra/codecs/xor/cyxor.cpython-*.so
333 %{py3_sitedir}/xpra/codecs/xor/*.py
334 %{py3_sitedir}/xpra/codecs/xor/__pycache__
335 %{py3_sitedir}/xpra/codecs/*.py
336 %{py3_sitedir}/xpra/codecs/__pycache__
337 %{py3_sitedir}/xpra/dbus
338 %dir %{py3_sitedir}/xpra/gtk_common
339 %dir %{py3_sitedir}/xpra/gtk_common/gtk3
340 %attr(755,root,root) %{py3_sitedir}/xpra/gtk_common/gtk3/gdk_atoms.cpython-*.so
341 %attr(755,root,root) %{py3_sitedir}/xpra/gtk_common/gtk3/gdk_bindings.cpython-*.so
342 %{py3_sitedir}/xpra/gtk_common/*.py
343 %{py3_sitedir}/xpra/gtk_common/__pycache__
344 %{py3_sitedir}/xpra/keyboard
345 %dir %{py3_sitedir}/xpra/net
346 %dir %{py3_sitedir}/xpra/net/bencode
347 %attr(755,root,root) %{py3_sitedir}/xpra/net/bencode/cython_bencode.cpython-*.so
348 %{py3_sitedir}/xpra/net/bencode/*.py
349 %{py3_sitedir}/xpra/net/bencode/__pycache__
350 %{py3_sitedir}/xpra/net/mdns
351 %{py3_sitedir}/xpra/net/websockets
352 %attr(755,root,root) %{py3_sitedir}/xpra/net/vsock.cpython-*.so
353 %{py3_sitedir}/xpra/net/*.py
354 %{py3_sitedir}/xpra/net/__pycache__
355 %{py3_sitedir}/xpra/notifications
356 %dir %{py3_sitedir}/xpra/platform
357 %dir %{py3_sitedir}/xpra/platform/xposix
358 %attr(755,root,root) %{py3_sitedir}/xpra/platform/xposix/netdev_query.cpython-*.so
359 %attr(755,root,root) %{py3_sitedir}/xpra/platform/xposix/sd_listen.cpython-*.so
360 %{py3_sitedir}/xpra/platform/xposix/*.py
361 %{py3_sitedir}/xpra/platform/xposix/__pycache__
362 %{py3_sitedir}/xpra/platform/*.py
363 %{py3_sitedir}/xpra/platform/__pycache__
364 %{py3_sitedir}/xpra/scripts
365 %dir %{py3_sitedir}/xpra/server
366 %{py3_sitedir}/xpra/server/auth
367 %{py3_sitedir}/xpra/server/dbus
368 %{py3_sitedir}/xpra/server/mixins
369 %{py3_sitedir}/xpra/server/proxy
370 %{py3_sitedir}/xpra/server/rfb
371 %{py3_sitedir}/xpra/server/shadow
372 %{py3_sitedir}/xpra/server/source
373 %dir %{py3_sitedir}/xpra/server/window
374 %attr(755,root,root) %{py3_sitedir}/xpra/server/window/motion.cpython-*.so
375 %{py3_sitedir}/xpra/server/window/*.py
376 %{py3_sitedir}/xpra/server/window/__pycache__
377 %attr(755,root,root) %{py3_sitedir}/xpra/server/cystats.cpython-*.so
378 %attr(755,root,root) %{py3_sitedir}/xpra/server/pam.cpython-*.so
379 %{py3_sitedir}/xpra/server/*.py
380 %{py3_sitedir}/xpra/server/__pycache__
381 %{py3_sitedir}/xpra/sound
382 %dir %{py3_sitedir}/xpra/x11
383 %dir %{py3_sitedir}/xpra/x11/bindings
384 %attr(755,root,root) %{py3_sitedir}/xpra/x11/bindings/*.so
385 %{py3_sitedir}/xpra/x11/bindings/*.py
386 %{py3_sitedir}/xpra/x11/bindings/__pycache__
387 %{py3_sitedir}/xpra/x11/dbus
388 %dir %{py3_sitedir}/xpra/x11/gtk3
389 %attr(755,root,root) %{py3_sitedir}/xpra/x11/gtk3/gdk_bindings.cpython-*.so
390 %attr(755,root,root) %{py3_sitedir}/xpra/x11/gtk3/gdk_display_source.cpython-*.so
391 %{py3_sitedir}/xpra/x11/gtk3/*.py
392 %{py3_sitedir}/xpra/x11/gtk3/__pycache__
393 %{py3_sitedir}/xpra/x11/gtk_x11
394 %{py3_sitedir}/xpra/x11/models
395 %{py3_sitedir}/xpra/x11/*.py
396 %{py3_sitedir}/xpra/x11/__pycache__
397 %attr(755,root,root) %{py3_sitedir}/xpra/monotonic_time.cpython-*.so
398 %attr(755,root,root) %{py3_sitedir}/xpra/rectangle.cpython-*.so
399 %{py3_sitedir}/xpra/*.py
400 %{py3_sitedir}/xpra/__pycache__
401 %{py3_sitedir}/xpra-%{version}-py*.egg-info
402
403 %files -n cups-backend-xpra
404 %defattr(644,root,root,755)
405 %attr(756,root,root) %{cupsdir}/xpraforwarder
This page took 0.129231 seconds and 3 git commands to generate.