Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Latest commit

 

History

History
150 lines (106 loc) · 6.5 KB

README.format.md

File metadata and controls

150 lines (106 loc) · 6.5 KB

GPOPT and ORCA code formatting

Tools

  1. We are using clang-format.

  2. We use the current stable release, with an eye to good new options coming from the next release. As of writing we're using release 10, the configuration options are documented here.

  3. As mentioned in the style guide, the format style is based on Google C++ style guide, but mixed in with Postgres formatting rules (break before braces, 4-space tabbing, etc)

  4. We should use an explicit, complete (locked down) specification for the .clang-format file.

  5. But our intent is better expressed as well organized, commented yaml. We use a simple script to generate the complete config file from the intent file. For example, on my Linux laptop, I run:

    CLANG_FORMAT=clang-format-10 src/tools/fmt gen

    If the correct version of clang-format is installed as clang-format (as is the case in macOS), you can omit the environment variable override.

  6. To check for formatting conformance, one can run

    src/tools/fmt chk

    It will succeed quietly (with return code 0) or point out the first few places that need to be formatted.

  7. To wholesale format all of ORCA and GPOPT

    src/tools/fmt fmt

    On my laptop this takes about 2.5 seconds.

  8. Of course, when you're writing code, 2.5 seconds is an eternity. Here's a non-exhaustive list of editor / IDE plugins that provide an integrated formatting experience. The in-editor formatting typically takes around 50ms. Depending on your plugin / editor, the formatting either happens automatically as you type, on save, or when you invoke it explicitly.

    • A community VIM plugin that looks promising and claims to be better than the official VIM integration
    • Clion detects .clang-format automatically and switches to using it for the built-in "Reformat Code" and "Reformat File...".

Annotating history

  1. It's usually desirable to skip past formatting commits when doing a git blame. Fortunately, git blame has two options that are extremely helpful:
    1. -w ignore whitespace
    2. --ignore-rev / --ignore-revs-file accepts commits to skip while annotating

When combined, -w --ignore-revs-file produces a perfectly clean annotation, unencumbered by a noisy history. This also gives us a peace of mind in changing our formats more frequently without worrying about hindering the git blame experience, rather than "do it once, set it in stone, and forget about it".

Reformatting in-flight patches

ORCA is actively developed, that means when the "big bang" formatting change is merged, there will inevitably be a number of patches that were started well before the formatting change, and these patches will now need to conform to the new format. The following steps are used to convert in-flight branches to the new format.

  1. Fetch the inflight PR. Let's say its greenplum-db/gpdb#20042

    git fetch origin refs/pull/20042/head
    git checkout -b 20042-backup FETCH_HEAD
  2. Duplicate the PR to a working branch. We'll reformat this branch:

    git checkout -b 20042-fmt
  3. Rebase the working branch to just before the big bang. Normally, you'd do it like (but don't do this yet):

    git rebase 'origin/main^{/Format ORCA and GPOPT}~'

    Here 'origin/main^{/Format ORCA and GPOPT}' is a Git notation that denotes the most recent commit from branch `origin/main' that contains the phrase "Format ORCA and GPOPT". The trailing tilde character is Git shorthand for "first parent".

  4. But! We want to insert a precursor commit that will eventually disappear:

    git rebase --interactive 'origin/main^{/Format ORCA and GPOPT}~2'

    When we edit the "rebase todo" in an editor, make sure to insert the following action between the first two "pick" action items:

    --- /tmp/todo	2020-11-12 16:48:07.251333950 -0800
    +++ /tmp/todo2	2020-11-12 16:48:07.291333698 -0800
    @@ -1,7 +1,8 @@
     pick 87fd0149caf8f052 Penultimate commit on main
    +exec git checkout origin/main -- src/tools/fmt src/include/gpopt/.clang-format src/backend/gpopt/.clang-format src/backend/gporca/.clang-format; git commit -m 'this commit will disappear'
     pick 93235faf306f4ecb 1st commit from PR
     pick 2b7ad8b9fd1f222c 2nd commit from PR
     pick 5bc7ac02c1c78b8b Last commit from PR
    
     # Rebase f96bb1e290ef188e..5bc7ac02c1c78b8b onto c6ab7beee96e8bc7 (2 commands)
     #

    What happens here is that we inserted a placeholder commit that gets us the format script and format configuration while rebasing.

    This commit will disappear in the final history (read on)

  5. Use git filter-branch to rewrite the branch history

    git filter-branch --force --tree-filter 'CLANG_FORMAT=clang-format-10 src/tools/fmt fmt; CLANG_FORMAT=clang-format-10 src/tools/fmt fmt' origin/main..

    Now we have reformatted every commit in this branch that's not in main (modulo the big bang commit). As a bonus, our placeholder commit should now be identical to the tip of main (the big bang formatting commit).

  6. Now that we have reformatted the history, rebase on top of main

    git rebase origin/main

    Git should be smart enough to drop our placeholder commit, and now the history is all properly formatted.