$30 off During Our Annual Pro Sale. View Details »

Eurucamp 2015: Deep Diving: How to Explore a new Codebase

Eurucamp 2015: Deep Diving: How to Explore a new Codebase

As a developer, diving in a new code base is not uncommon: you’ve just been hired, you change projects, you want to help an open source project, the open source library your project depends on is buggy, etc. It’s like swimming through a underwater cave, you don’t know what treasures or monsters you’ll find, if the path is treacherous, or if it’s a true labyrinth where you’ll get lost. However, if you plan your visit, you can prepare, equip yourself, and survive to find the gem you’re looking for…

code snippet to trace the whole call graph from a piece of code https://gist.github.com/toch/82fd93ca449500d21f00

Christophe Philemotte

August 01, 2015
Tweet

More Decks by Christophe Philemotte

Other Decks in Programming

Transcript

  1. Deep Diving:
    How to Explore a
    New Codebase
    Andy Spearing © 2009

    View Slide

  2. _toch
    toch
    Hi, I'm
    Christophe

    View Slide

  3. @matylda © 2011
    Intro

    View Slide

  4. @matylda © 2011
    The most
    common
    task

    View Slide

  5. continuous typing

    View Slide

  6. View Slide

  7. but
    continuous reading
    Jono Witts © 2008

    View Slide

  8. Each written line
    is read
    at least 1 time
    Gavin St. Ours © 20013

    View Slide

  9. ● 300 dev days
    ● 14633 LOC
    ● 634595 Changed lines
    ● → 634595 / 14633 ~ 43 changed LOC / LOC

    View Slide

  10. For 1 final line,
    I read at least
    43 lines.

    View Slide

  11. View Slide

  12. How to
    Dive
    into a project
    Stuart Hamilton © 2008

    View Slide

  13. DO NOT
    Wander
    without a plan
    Felix Esteban © 2004

    View Slide

  14. Journey
    Needs
    Plan
    Peter Southwood © 20011

    View Slide

  15. Plan
    1. Goal
    2. Map
    3. Equipment & Dive
    4. Next?
    Peter Southwood © 20011

    View Slide

  16. 1.
    Goal
    Peter Southwood © 20011

    View Slide

  17. ➔ fix a bug
    ➔ implement a feature
    ➔ write some doc
    ➔ style the code
    ➔ refactor a small piece of code
    ➔ simply use it

    View Slide

  18. View Slide

  19. http_proxy=http://127.0.0.1 \
    ruby -e "
    require 'open-uri'
    open(
    'http://google.com',
    proxy: nil
    )
    "

    View Slide

  20. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:878:in `initialize': Connection
    refused - connect(2) (Errno::ECONNREFUSED)
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:878:in `open'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:878:in `block in connect'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/timeout.rb:52:in `timeout'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:877:in `connect'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:862:in `do_start'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:851:in `start'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:313:in `open_http'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:708:in `buffer_open'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:210:in `block in open_loo
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:208:in `catch'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:208:in `open_loop'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:149:in `open_uri'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:688:in `open'
    from ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:34:in `open'
    from -e:1:in `'

    View Slide

  21. 2.
    Map
    Peter Southwood © 20011

    View Slide

  22. Find the Map
    ➔ Repository URI
    ➔ Project URI
    ➔ Intro Doc: README

    View Slide

  23. Find the Map
    ● https://github.com/ruby/ruby
    ● https://bugs.ruby-lang.org/
    ● https://github.com/ruby/ruby/blob/trunk/
    README.md

    View Slide

  24. Find the Legend

    View Slide

  25. a
    Legend

    View Slide

  26. Find the Legend
    ➔ CONTRIBUTING Guideline

    View Slide

  27. Find the Legend
    ➔ CONTRIBUTING Guideline
    https://github.com/ruby/ruby/blob/trunk/
    CONTRIBUTING.md

    View Slide

  28. Find the Legend
    ➔ CONTRIBUTING Guideline
    https://github.com/ruby/ruby/blob/trunk/
    CONTRIBUTING.md

    View Slide

  29. Find the Legend
    ➔ CONTRIBUTING Guideline
    ➔ Directory Structure

    View Slide

  30. Find the Legend
    ➔ CONTRIBUTING Guideline
    ➔ Directory Structure

    View Slide

  31. Find the Legend
    ➔ CONTRIBUTING Guideline
    ➔ Directory Structure
    ➔ Talk to other contributors, maintainers

    View Slide

  32. Find the Legend
    ➔ CONTRIBUTING Guideline
    ➔ Directory Structure
    ➔ Talk to other contributors, maintainers
    ➔ Participate to the dev meeting

    View Slide

  33. If blocked?
    ➔ ASK!

    View Slide

  34. Boris Dimitrov © 20009
    3.
    Equipment
    & Dive

    View Slide

  35. Get a Toolbelt
    ➔ Pick an Editor

    View Slide

  36. xkcd

    View Slide

  37. Get a Toolbelt
    ➔ Pick an Editor
    ➔ Bundle

    View Slide

  38. $ cd GitLab
    $ bundle viz

    View Slide

  39. $ cd GitLab
    $ bundle viz

    View Slide

  40. $ cd GitLab
    $ bundle viz

    View Slide

  41. Get a Toolbelt
    ➔ Pick an Editor
    ➔ Bundle
    ➔ Run Tests

    View Slide

  42. Get a Toolbelt
    ➔ Pick an Editor
    ➔ Bundle
    ➔ Run Tests
    ➔ Others

    View Slide

  43. Get a Toolbelt
    ➔ ST3
    ➔ Apply a Patch & Use it
    ➔ MRI WIKI DeveloperHowto
    ➔ Sign up to Ruby Redmine

    View Slide

  44. Use your Toolbelt
    ➔ Run the App & Use it

    View Slide

  45. http_proxy=http://127.0.0.1 \
    ruby -e "
    require 'open-uri'
    open(
    'http://google.com',
    proxy: nil
    )
    "

    View Slide

  46. Use your Toolbelt
    ➔ Run the App & Use it
    ➔ Read the Code

    View Slide

  47. $ wc -l *.rb
    1001 common.rb
    257 ftp.rb
    1676 generic.rb
    106 http.rb
    22 https.rb
    260 ldap.rb
    20 ldaps.rb
    280 mailto.rb
    3622 total
    open-uri

    View Slide

  48. ➔ Find proxy management
    ➔ Understand how open_http works
    ➔ Spot the bug
    URI

    View Slide

  49. ➔ Trace the Calls
    Dive into URI

    View Slide

  50. def get_call_graph_on
    scope = {}
    trace = TracePoint.new(:call, :line) do |tp|
    case tp.event
    when :call then puts "#{tp.path}:#{tp.lineno} #{tp.defined_class}::#{tp.method_id} called from " \
    "#{scope[:path]}:#{scope[:lineno]} #{scope[:class]}::#{scope[:method_id]}"
    when :line then scope = {
    event: :line,
    lineno: tp.lineno,
    path: tp.path,
    class: tp.defined_class,
    method_id: tp.method_id
    }
    end
    end
    trace.enable
    yield
    trace.disable
    end

    View Slide

  51. require 'open-uri'
    get_call_graph_on do
    open(
    'http://google.com',
    proxy: nil
    )
    end

    View Slide

  52. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:28 Kernel::open
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:746 #::parse
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:209 URI::Parser::parse
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:120 URI::Parser::split
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/http.rb:83 URI::HTTP::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:173 URI::Generic::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:342 URI::Generic::set_scheme
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:523 URI::Generic::set_userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:556 URI::Generic::split_userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:617 URI::Generic::set_host
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:709 URI::Generic::set_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:842 URI::Generic::set_path
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:907 URI::Generic::set_query
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:970 URI::Generic::set_opaque
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:779 URI::Generic::set_registry
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:1013 URI::Generic::set_fragment
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:36 URI::Generic::default_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:29 #::defaul
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:36 URI::Generic::default_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:29 #::defaul
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:709 URI::Generic::set_port

    View Slide

  53. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:28 Kernel::open
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:746 #::parse
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:209 URI::Parser::parse
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:120 URI::Parser::split
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/http.rb:83 URI::HTTP::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:173 URI::Generic::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:342 URI::Generic::set_scheme
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:523 URI::Generic::set_userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:556 URI::Generic::split_userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:617 URI::Generic::set_host
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:709 URI::Generic::set_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:842 URI::Generic::set_path
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:907 URI::Generic::set_query
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:970 URI::Generic::set_opaque
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:779 URI::Generic::set_registry
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:1013 URI::Generic::set_fragment
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:36 URI::Generic::default_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:29 #::defaul
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:36 URI::Generic::default_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:29 #::defaul
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:709 URI::Generic::set_port

    View Slide

  54. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/http.rb:83 URI::HTTP::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:173 URI::Generic::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:342 URI::Generic::set_scheme
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:523 URI::Generic::set_userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:556 URI::Generic::split_userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:617 URI::Generic::set_host
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:709 URI::Generic::set_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:842 URI::Generic::set_path
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:907 URI::Generic::set_query
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:970 URI::Generic::set_opaque
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:779 URI::Generic::set_registry
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:1013 URI::Generic::set_fragment
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:36 URI::Generic::default_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:29 #::defaul
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:36 URI::Generic::default_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:29 #::defaul
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:709 URI::Generic::set_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:687 OpenURI::OpenRead::open
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:130 #::open_uri

    View Slide

  55. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:29 #::defaul
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:709 URI::Generic::set_port
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:687 OpenURI::OpenRead::open
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:130 #::open_uri
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:120 #::scan_open_opt
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:111 #::check_options
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:166 #::open_loop
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:376 OpenURI::Buffer::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:707 URI::HTTP::buffer_open
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:253 #::open_http
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:571 URI::Generic::userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:889 #::suffixe
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb:1168 #unresolved_deps
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3

    View Slide

  56. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:707 URI::HTTP::buffer_open
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:253 #::open_http
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:571 URI::Generic::userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:889 #::suffixe
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb:1168 #unresolved_deps
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:889 #::suffixe
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb:1168 #unresolved_deps
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3

    View Slide

  57. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:707 URI::HTTP::buffer_open
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/open-uri.rb:253 #::open_http
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:571 URI::Generic::userinfo
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:889 #::suffixe
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb:1168 #unresolved_deps
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:889 #::suffixe
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb:1168 #unresolved_deps
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3

    View Slide

  58. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:889 #::suffixe
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb:1168 #Specification>::unresolved_deps
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:889 #::suffixe
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb:1168 #Specification>::unresolved_deps
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:3
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:183 MonitorMixin::mon_enter
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb:1118 #::find_u

    View Slide

  59. ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:194 MonitorMixin::mon_exit
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb:244 MonitorMixin::mon_check_owner
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:660 URI::Generic::hostname
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/http.rb:95 URI::HTTP::request_uri
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:1442 URI::Generic::path_query
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:608 #::new
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:632 Net::HTTP::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:993 #::proxy_class
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:847 Net::HTTP::start
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:861 Net::HTTP::do_start
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:867 Net::HTTP::connect
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:1012 Net::HTTP::proxy?
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http.rb:1026 Net::HTTP::proxy_uri
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:990 Kernel::URI
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:746 #::parse
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:209 URI::Parser::parse
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:120 URI::Parser::split
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb:659 #::scheme_list
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/http.rb:83 URI::HTTP::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:173 URI::Generic::initialize
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:342 URI::Generic::set_scheme
    ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb:523 URI::Generic::set_userinfo

    View Slide

  60. http = klass.new(
    target_host,
    target_port
    )

    View Slide

  61. ➔ Trace the Calls
    ➔ Search the Source
    Dive into URI

    View Slide

  62. Search the Source
    $ grep -nr "open_http".
    ./open-uri.rb:253: def OpenURI.open_http(buf, target, proxy, option
    ./open-uri.rb:708: OpenURI.open_http(buf, self, proxy, options)
    ./open-uri.rb:717: OpenURI.open_http(buf, self, proxy, option

    View Slide

  63. Search the Source
    $ grep -rn "class HTTP " .
    ./net/http.rb:384: class HTTP < Protocol
    ./uri/http.rb:22: class HTTP < Generic

    View Slide

  64. Search the Source
    $ EDITOR=subl \
    bundle open gitlab_omniauth-ldap

    View Slide

  65. ➔ Trace the Calls
    ➔ Search the Source
    ➔ Get Context with a Test
    Dive into URI

    View Slide

  66. Get Context with a Test
    context "without params['markdown_img']" do
    it "returns an error" do
    get_call_graph_on do
    post :upload_image, id: project.to_param, format: :json
    end
    expect(response.status).to eq(422)
    end
    end

    View Slide

  67. Use your Toolbelt
    ➔ Run the App & Use it
    ➔ Read the Code
    ➔ Edit the Code

    View Slide

  68. http = proxy ?
    klass.new(target_host, target_port) :
    klass.new(target_host, target_port, nil)

    View Slide

  69. Use your Toolbelt
    ➔ Run the App & Use it
    ➔ Read & Edit the Code
    ➔ Report a bug
    ➔ Submit a contribution

    View Slide

  70. View Slide

  71. If blocked?
    ➔ ASK!

    View Slide

  72. 4.
    Next?
    Peter Southwood © 20011

    View Slide

  73. How long?
    ➔ Keep it reasonable at first
    ➔ From ½ to 1 day

    View Slide

  74. Find Next Goal
    ➔ Fix a bug
    ➔ Develop a feature
    ➔ Run Static Analysis Tools
    ➔ Review a PullRequest

    View Slide

  75. Iterate
    ➔ :)
    Jean-Marc Kuffer © 2007

    View Slide

  76. If blocked?
    ➔ ASK!

    View Slide

  77. Outro
    1. Goal
    2. Map
    3. Equipment & Dive

    View Slide

  78. ?
    _toch
    toch

    View Slide