zoukankan      html  css  js  c++  java
  • Adding hooks to gclient deps

     

    In the previous several posts, we got to the point of being able to sync a git repo along with some dependencies. For reference, here's the .gclient file we created so far as well as the .DEPS.git from my_project directory:

    $ cat .gclient
    solutions = [
      { "name"        : "my_project",
        "url"         : "ssh://example.com/repos/my_project.git",
        "deps_file"   : ".DEPS.git",
        "managed"     : True,
        "custom_deps" : {
        },
        "safesync_url": "",
      },
    ]
    cache_dir = None
    
    $ cat my_project/.DEPS.git
    vars = {
      # Common settings.
      "base_url" : "ssh://example.com/repos",
      "project_directory" : "my_project",
    
      # Specify dependency package |package| as package_destination, package_url,
      # and package_revision tuples. Then, ensure to add the dependency in deps
      # using the variables.
    
      # Google test
      "googletest_destination" : "third_party/googletest",
      "googletest_url" : "/external/googletest.git",
      "googletest_revision" : "2a2740e0ce24acaae88fb1c7b1edf5a2289d3b1c",
    }
    
    deps = {
      # Google test
      Var("project_directory") + "/" + Var("googletest_destination") :
          Var("base_url") + Var("googletest_url") + "@" + Var("googletest_revision")
    }
    

    Now, in the last post, I noted that the initial checkout seems to happen in a detached state. That is, git status prints out something along the lines of the following:

    HEAD detached at origin/master
    

    I would like my initial checkouts to always go to the master branch, since I know I will forget to switch to the master branch when doing changes. This seems like a good application of a hook.

    As you recall, .DEPS.git from Chromium had a section called hooks. Great! I would imagine that's exactly what we want.

    The structure seems to be as follows:

    hooks = [
      {
        "name" : "hook_name",
        "pattern" : "hook_pattern",
        "action" : ["hook_action", "hook_action_parameter1"]
      }
    ]
    

    Name and action are fairly self explanatory, but I'm not too clear about what the pattern is supposed to represent. Run this hook only if something matches this pattern? That would make sense. However, most of the hooks in Chromium .DEPS.git have pattern as ".", so let's stick with that for now.

    Let's just jump in and add a simple hook into our .DEPS.git:

    ...
    hooks = [
      {
        "name" : "hello",
        "pattern" : ".",
        "action" : ["echo", "hello world!"]
      }
    ]
    

    This should do something:

    $ gclient runhooks
    
    ________ running 'echo hello world!' in '/tmp/learning_gclient'
    hello world!
    $ gclient sync
    Syncing projects: 100% (2/2), done.                             
    
    ________ running 'echo hello world!' in '/tmp/learning_gclient'
    hello world!
    

    Perfect! We can run hooks separately, and the hooks are run when we sync. That's exactly what we want. One observation I have is that it's probably a good idea to stick to some sort of a cross platform scripting language when writing hooks, since 'echo' on my machine might not exist on some other machine. Since gclient itself is written in python, it's a good bet that python is installed. As such, let's stick with python as the hooks language.

    Also note that we're running this hook in the same directory as the .gclient file (/tmp/learning_gclient in my case). Switching into my_project and running hooks again confirms that we're always running it from the same directory as the .gclient file. 

    Alright, let's just jump in and write a hook that checkout out master if the current state is "HEAD detached at origin/master". Learning python is out of the scope of this post, but after some googling on how to do things in it I came up with this:

    $ cat my_project/hooks/checkout_master.py
    import os
    from subprocess import Popen, PIPE
    
    def main():
      os.chdir("my_project")
      p = Popen(['git', 'status'], stdout=PIPE)
      output, err = p.communicate()
    
      line = output.splitlines()[0].strip()
      if line != 'HEAD detached at origin/master':
        print 'not an initial checkout, skip checkout master'
        return
    
      print 'checking out master branch'
      p = Popen(['git', 'checkout', 'master'], stdout=PIPE, stderr=PIPE)
      output, err = p.communicate()
      
    if __name__ == "__main__":
      main()
    

    Basically, we switch to my_project (I don't like hardcoding the project name here, but it will do for now), get the output of "git status", and if the first line of that is 'HEAD detached at origin/master', we run "git checkout master". Now, let's add this hook into our .DEPS.git, replacing the hello world one:

    ...
    hooks = [ 
      {
        "name" : "checkout_master",
        "pattern" : ".",
        "action" : ["python", Var("project_directory") + "/hooks/checkout_master.py"]
      }
    ]
    

    Let's see if that works as expected:

    $ gclient runhooks
    
    ________ running '/usr/bin/python my_project/hooks/checkout_master.py' in '/tmp/learning_gclient'
    not an initial checkout, skip checkout master
    

    Right, that's because during my testing, I already switched to the master branch. Let's just delete the whole project and sync again. However, remember to commit/push your changes. During my first attempt, I removed the directory and lost all of my changes (ie, I had to write the script and the hooks again).

    $ rm -rf my_project
    $ gclient sync
    Syncing projects: 100% (2/2), done.                             
    
    ________ running '/usr/bin/python my_project/hooks/checkout_master.py' in '/tmp/learning_gclient'
    checking out master branch
    $ cd my_project/
    $ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    
    nothing to commit, working directory clean
    

    Excellent! Everything seems to be working as intended. I think I'm happy enough with this basic gclient setup to move on to the actual build system using either GYP or GN.

    - vmpstr

    P.S. To eliminate the project name from checkout_master.py (thus making it a generic hook for any project), we should just move the project name to be a parameter. Here's a diff that makes it so:

    diff --git a/.DEPS.git b/.DEPS.git
    index 482ee29..56555cd 100644
    --- a/.DEPS.git
    +++ b/.DEPS.git
    @@ -23,6 +23,10 @@ hooks = [
       {
         "name" : "checkout_master",
         "pattern" : ".",
    -    "action" : ["python", Var("project_directory") + "/hooks/checkout_master.py"]
    +    "action" : [
    +      "python",
    +      Var("project_directory") + "/hooks/checkout_master.py",
    +      Var("project_directory")
    +    ]
       }
     ]
    diff --git a/hooks/checkout_master.py b/hooks/checkout_master.py
    index f41eefa..b5cf30a 100644
    --- a/hooks/checkout_master.py
    +++ b/hooks/checkout_master.py
    @@ -1,8 +1,10 @@
     import os
     from subprocess import Popen, PIPE
    +import sys
     
     def main():
    -  os.chdir("my_project")
    +  if len(sys.argv) == 2:
    +    os.chdir(sys.argv[1])
       p = Popen(['git', 'status'], stdout=PIPE)
       output, err = p.communicate()
  • 相关阅读:
    Spring MVC-静态页面示例(转载实践)
    Spring MVC-页面重定向示例(转载实践)
    Spring中获取Session的方法汇总
    Spring Boot项目@RestController使用重定向redirect
    MySQL Workbench常用快捷键及修改快捷键的方法
    Eclipse安装Jetty插件(Web容器)
    Java EE: XML Schemas for Java EE Deployment Descriptors(Java Web的web.xml头web-app标签上的XML模式)
    Ubuntu 16.04 GNOME在桌面左侧添加启动器(Launcher)
    Ubuntu 16.04 GNOME添加桌面图标/在桌面上显示图标
    Ubuntu 16.04修改显示字体大小(包括GNOME/Unity)
  • 原文地址:https://www.cnblogs.com/fire909090/p/11212209.html
Copyright © 2011-2022 走看看