Git trick #481: Prevent accidentally pushing into git instead of Gerrit

Some while ago I wrote about a little [git hook that automatically sets up your commit author identity][1]  after git clone based on the remote origin address. Recently I learned that in git 2.8 a new pre-push hook was introduced, and I immediately knew it will fix my second biggest pain point: accidentally pushing directly into git instead of Gerrit.

If you often switch between different projects where some use Gerrit for code review and some don’t, it’s very easy to just mistakenly do

git push master

when in fact you wanted to

git push HEAD:refs/for/master

There are some tricks how to make it harder for you to accidentally do this, like creating a “gpush” alias that pushes to refs/for/master and disabling pushing into the ‘origin’ remote by changing the push URL to something invalid. That, however, is not perfect because there are still ways how to by-pass it. And it becomes complicated if you use more than one remote and it’s clumsy if you sometimes do want to push directly into git (for example to submit a large patch series).

With a custom pre-push hook, we can check if the remote that we are pushing into is a Gerrit instance and then check if the remote ref that we are pushing into is a “Gerrit ref” (refs/for/foo) instead of a regular branch and we can have a nice “Are you sure you want to do this?” prompt:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# (C) 2017 Daniel Vrátil <dvratil@kde.org>
# License: GPL

import os
import sys

def remoteIsGerrit(remoteName, remoteUrl):
    # if the remote is called "gerrit", assume it's Gerrit
    if 'gerrit' in remoteName:
        return True
    # if the remote URL contains the default Gerrit port, assume it's Gerrit
    if ':29418/' in remoteUrl:
        return True

    # TODO: Add custom checks to match your non-standard Gerrit configuration
    return False
def main():
    # name and URL of the remote we are pushing into is passed as arguments
    if not remoteIsGerrit(sys.argv[1], sys.argv[2]):
        # If we are not pushing into gerrit, then simply allow the push
        return
    # The pushed refs are passed in via stdin
    for line in sys.stdin:
        # line = "localRef localRev remoteRef remoteRev"
        remoteRef = line.split(' ')[2]
        # Check if the remoteRef contains the typical Gerrit 'refs/for/foo'.
        if not remoteRef.startswith('refs/for/'):
            print('!!')
            print('!! You are pushing directly into git instead of Gerrit !!')
            print('!! Do you want to continue? [y/N] ', end = '', flush = True)
            if open('/dev/tty', 'rb').readline().decode().strip().lower() == 'y':
                return
            else:
                sys.exit(1)

if __name__ == "__main__":
    main()

Save this a file as “pre-push” and move it into .git/hooks/ folder in your local repository clone. Remember to make the script executable.

Here is how it works: trying to push into “gerrit” remote to branch “5.9” directly gets intercepted by our new hook and if you press ‘n’ the push gets aborted. If I would’ve pressed ‘y’, then the push would proceed.

$ git push gerrit 5.9
Enter passphrase for key '/home/dvratil/.ssh/id_rsa.qt':  
!! 
!! You are pushing directly into git instead of Gerrit !! 
!! Do you want to continue? [y/N] n
error: failed to push some refs to 'ssh://dvratil@codereview.qt-project.org:29418/qt/qtbase.git'</pre>
<p>Now when we try to push to the correct ref (`refs/for/5.9`) the hook accepts the push without any complaints:</p>
<pre>$ git push gerrit HEAD:refs/for/5.9
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 407 bytes, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2)
remote: Processing changes: new: 1, refs: 1, done    
remote: 
remote: New Changes:
remote:   https://codereview.qt-project.org/......
remote: 
To ssh://dvratil@codereview.qt-project.org:29418/qt/qtbase
 * [new branch] HEAD -&gt; refs/for/5.9

To have the hook automatically copied into every new repository that you clone, save it as “pre-push” into .git-templates/hooks/ and run the following command:

git config --global init.templatedir ~/.git-templates

Git will automatically copy everything from the ‘templatedir’ into the .git directory after every new git clone, so you don’t need to bother with doing that manually. Unfortunately for all your existing checkouts, you have to copy the hook manually

[1] /2015/12/git-trick-628-automatically-set-commit-author-based-on-repo-url

Plasma 5.6 beta available on Fedora

Plasma 5.6 will be out in two weeks but the Plasma team has just released Plasma 5.6 beta which already features all the new yummy things and improvements as well as bunch of bug fixes that will be available in the 5.6 release.

Among other things Plasma 5.6 brings improved color scheme support, task manager on steroids, some new applets as well as further progress on the Wayland front. Two completely new things come as a tech preview: GRUB2 and Plymouth themes to make your system look fancy from the first second you power it up (see instructions below how to enable them).

You can ready the release announcement with more detailed descriptions and screenshots here.

The Fedora KDE SIG team has updated the Plasma 5 Unstable Copr repository so you can get a taste of Plasma 5.6 on Fedora 23 now (sorry for the lack of F22 builds). Rawhide will probably get the beta update some time next week.

$ dnf copr enable @kdesig/plasma-5-unstable
$ dnf update

Due to some changes in upstream releases of KActivities it is possible that you will get package conflict between kactivitymanagerd-debuginfo and kf5-kactivities-debuginfo. In that case please uninstall the kf5-kactivities-debuginfo package. This will be fixed properly once we roll out KDE Frameworks 5.20.

 

If you want to try the new GRUB and Plymouth themes, install the new packages

$ dnf install grub2-breeze-theme plymouth-theme-breeze

To enable the GRUB theme, edit /etc/default/grub:

GRUB_TERMINAL_OUTPUT="gfxterm"
GRUB_THEME=/boot/grub2/themes/breeze/theme.txt

and generate new GRUB configuration:

$ grub2-mkconfig -o /boot/grub2/grub.cfg

To enable the Plymouth theme, run

plymouth-set-default-theme breeze --rebuild-initrd

 

If you run into any packaging issues, please talk to us on #fedora-kde on IRC or kde@lists.fedoraproject.org. If you find any bugs or crashes, please report them to bugs.kde.org so that Plasma developers can fix them before the final 5.6 release.

Git trick #628: automatically set commit author based on repo URL

If you have more than one email identity that you use to commit to different projects you have to remember to change it in .git/config every time you git clone a new repository. I suck at remembering things and it’s been annoying me for a long time that I kept pushing commits with wrong email addresses to wrong repositories.

I can’t believe I am the only one having this problem, but I could not find anything on the interwebs so I just fixed it myself and I’m posting it here so that maybe hopefuly someone else will find it useful too :).

The trick is very simple: we create a post-checkout hook that will check the value of user.email in .git/config and set it to whatever we want based on URL of the “origin” remote.  Why post-checkout? Because there’s no post-clone hook, but git automatically checkouts master after clone so the hook gets executed. It also gets executed every time you run git checkout by hand but the overhead is minimal and we have a guard against overwriting the identity in case it’s already set.

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# (C) 2015 Daniel Vrátil &lt;dvratil@kde.org&gt;
# License: GPL
#
# Requires: Python 2 or 3 and compatible GitPython
#
# https://github.com/gitpython-developers/GitPython
import git
import ConfigParser
import os
import sys

repo = git.Repo(os.getcwd())

# Don't do anything if an identity is already configured in this
# repo's .git/config
config = repo.config_reader(config_level = 'repository')
try:
    # The value of user.email is non-empty, stop here
    if config.get_value('user', 'email'):
        sys.exit(0)
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
    # Section or option does not exist, continue
    pass
origin = repo.remote('origin')
if not origin:
    print('** Failed to detect remote origin, identity not updated! **')
    sys.exit(0)
# This is where you adjust the code to fit your needs
if 'kde.org' in origin.url or origin.url.startswith('kde:'):
    email = 'dvratil@kde.org'
elif 'fedoraproject.org' in origin.url:
    email = 'dvratil@fedoraproject.org'
elif 'kdab.com' in origin.url:
    email = 'daniel.vratil@kdab.com'
else:
    print('** Failed to detect identity! **')
    sys.exit(0)
# Write the option to .git/config
config = repo.config_writer()
config.set_value('user', 'email', email)
config.release()
print('** User identity for this repository set to \'%s\' **' % email)

To install it, just copy the script above to ~/.git-templates/hooks/post-checkout, make it executable and run

git config --global init.templatedir ~/.git-templates

All hooks from templatedir are automatically copied into .git/hooks when a new repository is created (git init or git clone) - this way the hook will get automatically deployed to every new repo.

And here’s a proof that it works :-)

[dvratil@Odin ~/devel/KDE]
$ git clone kde:kasync
Cloning into 'kasync'...
remote: Counting objects: 450, done.
remote: Compressing objects: 100% (173/173), done.
remote: Total 450 (delta 285), reused 431 (delta 273)
Receiving objects: 100% (450/450), 116.44 KiB | 0 bytes/s, done.
Resolving deltas: 100% (285/285), done.
Checking connectivity... done.
** User identity for this repository set to 'dvratil@kde.org' **

[dvratil@Odin ~/packaging/fedpkg]
$ git clone ssh://dvratil@pkgs.fedoraproject.org/gammaray
Cloning into 'gammaray'...
remote: Counting objects: 287, done.
remote: Compressing objects: 100% (286/286), done.
remote: Total 287 (delta 113), reused 0 (delta 0)
Receiving objects: 100% (287/287), 57.24 KiB | 0 bytes/s, done.
Resolving deltas: 100% (113/113), done.
Checking connectivity... done.
** User identity for this repository set to 'dvratil@fedoraproject.org' **

Update 1: added utf-8 coding (thanks, Andrea) Update 2: changed shebang to more common /usr/bin/python (/bin/python is rather Fedora-specific), added “Requires” comment to top of the script (thanks, Derek)

Plasma 5.3 for Fedora

Fedora logoPlasma 5.3, new feature release of KDE workspace, has been released on Tuesday and you can get it now on Fedora.

Plasma 5.3 brings new features, improvements and almost 400 bug fixes for basically all of its components ranging from power management to various applets.

For users of Fedora 20 and Fedora 21 the traditional COPR repository has been updated. If you already use it just do yum update. If you want to switch to Plasma 5 from KDE 4 just follow the instructions on the main page.

Fedora 22, which is currently in beta, already has the 5.3 update in updates-testing and we are continuously polishing the update. For all KDE users updating to Fedora 22, when it's released in May, it will also mean final bye bye to KDE 4 and switch to Plasma 5. Fedora 22 repositories also features the latest release of KDE Telepathy, which finally brings IM integration into Plasma 5.

If you want to try out Plasma 5.3 on Fedora but don't want to install it on your computer yet there's, as always, a live ISO available for you based on Fedora 22 beta. And this time I did include a working installer (for real!), so when you change your mind just click "Install" ;-)

We welcome any feedback and testing from users, feel free to report any bugs to bugzilla.redhat.com, talk to us on #fedora-kde IRC channel on Freenode or join our mailing list.

Fedora RPM: Automatic "Provides" for CMake projects packages

If you ever did any RPM packaging (not just on Fedora) you probably noticed that some SPEC files don't use package names in BuildRequires fields but instead they refer to pkg-config module names, like this:

Name:           qt5-qtbase
Version:        5.4.1
Release:        1%{?dist}
...
BuildRequires:  pkgconfig(dbus-1)
BuildRequires:  pkgconfig(fontconfig)
BuildRequires:  pkgconfig(gl)
BuildRequires:  pkgconfig(glib-2.0)
BuildRequires:  pkgconfig(gtk+-2.0)
...

This is achieved by the respective packages simply having these aliases as their Provides (for example dbus-devel package Provides: pkgconfig(dbus-1)). The Provides are extracted automatically by an RPM script when the package is being built which gave me an idea...what if we could do the same for CMake modules?

And so I've written a simple script for RPM which extracts CMake package name and version from the package config files installed to /usr/lib/cmake. Simply put it means that kf5-kcoreaddons-devel will have

Provides:       cmake(KF5CoreAddons) = 5.8.0

and qt5-qtdeclarative-devel will have

Provides:       cmake(Qt5Qml) = 5.4.1
Provides:       cmake(Qt5Quick) = 5.4.1
Provides:       cmake(Qt5QuickTest) = 5.4.1
Provides:       cmake(Qt5QuickWidgets) = 5.4.1

...and all this happens automatically :-)

So, if you are packaging a CMake-based projects for Fedora you don't have to wonder which package provides the needed dependencies but you can just use the name from find_package() in BuildRequires and be done with it.

Name:           plasma-workspace
Version:        5.2.1
Release:        6%{?dist}
Summary:        Plasma workspace, applications and applets
...
BuildRequires:  cmake(Qt5Widgets) cmake(Qt5Quick) cmake(Qt5QuickWidgets) cmake(Qt5Concurrent) cmake(Qt5Test) cmake(Qt5Script) cmake(Qt5Network) cmake(Qt5WebKitWidgets)
BuildRequires:  cmake(Phonon4Qt5)
BuildRequires:  cmake(KF5Plasma) cmake(KF5DocTools) cmake(KF5Runner) ...
...

Another advantage is that this makes it easier to automate dependencies extraction from CMakeLists because we will no longer have to bother with mapping the CMake names to package names (for reference I have wrote a script to mass-update dependencies of all our KDE Frameworks 5 packages in Fedora).

We have pushed the script into Fedora's cmake package (currently in rawhide and (soon) in F22 but eventually I'd like to have it in F20 and F21 too) so all packages that will be rebuilt after this will get the automatic Provides.

In the long-term we would like to try to get the script to upstream RPM so that other distributions can use this too. For now the script is available in cmake package distgit.

Plasma 5.2 arrives to Fedora

It's here! Plasma 5.2 has been released just yesterday and you don't have to wait a single minute longer to update your beloved Fedora boxes :-)

I won't go into detail here about all the new awesome things that are waiting for you in Plasma 5.2, but I totally recommend that you go and read Plasma 5.2: The Quintessential Breakdown by Ken Vermette while you are waiting for your package manager to wade through the update. You can also read the official Plasma 5.2 release announcement, it has fancy animated screenshots ;).

And there's other news related to Plasma 5.2 and Fedora: Fedora rawhide has bee updated to Plasma 5.2 too. This means that KDE SIG will ship Plasma 5 in Fedora 22! Of course we will still maintain the Copr repository for our Fedora 20 and Fedora 21 users.

So, how to get Plasma 5.2 on Fedora?

On rawhide, just do dnf update. On Fedora 20 and Fedora 21, if you are already running Plasma 5.1.2 from dvratil/plasma-5 Copr, then all you need to do is to run dnf update. If you are running Plasma 5.1.95 (aka Plasma 5.2 beta) from dvratil/plasma-5-beta Copr, then it's time to switch back to stable:

dnf copr disable dvratil/plasma-5-beta
dnf copr enable dvratil/plasma-5
dnf update

If you are still running KDE 4 and you want to update to Plasma 5.2, just follow the instructions on dvratil/plasma-5 Copr page.

And if you don't feel like installing Plasma 5 on your production box right away and would like to just try it out, there's a live ISO for you. This time I did not forget to add Anaconda, so once you decide that Plasma 5 is good enough for you, you can just install it right from the ISO ;-)

EDIT: I might have included Anaconda, but did not add grub2 to the ISO, so the installer would fail anyway. This has been fixed and updated images are available now on the same link. If you are planning to install from the live ISO, please download the updated images (29-Jan-2015 00:42)

 

Oh, and if anyone is around in Brno next week for DevConf, let us know and we can informally meet for ceremonious consumption of beer to celebrate the Plasma release ;)

Plasma 5.2 Beta available for Fedora testers

On Tuesday KDE has released first beta of the upcoming Plasma 5.2. Plasma 5.2 is adding many new features and improvements and we would welcome testers to help find and fix bugs before the final release.

Fedora 21 with Plasma 5.2 beta Fedora users are welcome to try out Plasma 5.2 beta, either by running Fedora Plasma 5.2 beta live ISO, or by installing packages from plasma-5-beta Copr (see Installation Instructions on the Copr page)

Check out the release announcement to see what new features and improvements are waiting for you in Plasma 5.2. Final release will be in two weeks on January 27, after that we will update the plasma-5 Copr to get the update to all our users :-)

KDE Frameworks 5.3 and KDE Plasma 5.1 for Fedora are ready!

Fedora KDE SIG is happy to announce that latest version of KDE Frameworks 5 have just reached stable repositories of Fedora and  brand new version of KDE Plasma 5 is now available in the our Plasma 5 COPR.

KDE Frameworks 5.3.0

The third release of KDE Frameworks brings mostly bugfixes. KDE Frameworks 5 is a collection of libraries and software frameworks created by the KDE community. It's an effort to rework KDE 4 libraries into a set of individual and independent, cross platform modules that will be readily available to all Qt-based applications.

KDE Frameworks 5 are available in official Fedora repositories for Fedora 20 and the upcoming Fedora 21.

KDE Plasma 5.1

Fedora 20 running KDE Plasma 5KDE Plasma 5 is the next generation of KDE workspace based on Qt 5 and KDE Frameworks. It's latest version brings many bug fixes, performance improvements but also many new features! Dark color theme for the Breeze style, more widgets, improved Task switcher, reworked tray icons and much more. You can read about all the new things in Plasma 5.1 in the official release announcement.

To install KDE Plasma 5 on Fedora, just add the Plasma 5 COPR repository to yum, and simply run yum install plasma-5.

Live ISO

Do you want to give Plasma 5 a try, but don't want to install it yet? Easy! We have prepared a live ISO image based on Fedora 20 for you! You can get it from here: http://pub.dvratil.cz/plasma/iso/5.1/ (use Torrent for faster download).

Do you need help? Come talk to us: either on #fedora-kde IRC channel on Freenode, or join our mailing list kde@lists.fedoraproject.org.

Fedora 20 running KDE Plasma 5

KDE Frameworks 5 Beta and Plasma Next preview on Fedora!

The Fedora KDE SIG brings you all the new and cool stuff from KDE Frameworks and Plasma Next worlds!

First, our Copr repository with KDE Frameworks has been updated to 4.99.0 release, so go get it! All frameworks are co-installable with KDE 4, so you can develop against KF5 without needing any special setup. Also KDE Frameworks 5 were approved as feature for Fedora 21, which means that in next Fedora release, we will ship all Frameworks in the Fedora repositories! There are already some packages imported into rawhide, the rest will follow in next weeks.

And now for the awesome news: we have a live ISO with Plasma Next preview!

Fedora Plasma Next Live ISO Login screen

We packaged as much as we could (but still not everything!), including Rekonq, Dolphin, System Settings, Baloo, Milou and more - all built against Qt 5 and KDE Frameworks 5 of course.

Download Fedora Plasma Next Live ISO or get it via torrent.

Fedora Plasma Fedora Plasma

If you are really interested in trying locally, you can check out all the additional packages from kde-frameworks-unstable and plasma-next COPRs, but remember that all packages from those repositories install to /usr, so you will get conflicts with KDE 4 packages.