diff --git a/lib/pivotal_git_scripts/git_pair.rb b/lib/pivotal_git_scripts/git_pair.rb index 468fc35..5b16098 100644 --- a/lib/pivotal_git_scripts/git_pair.rb +++ b/lib/pivotal_git_scripts/git_pair.rb @@ -62,11 +62,21 @@ def commit(argv) author_details = extract_author_details_from_config(config, current_pair_initials) author_names = author_details.keys.map { |i| author_details[i][:name] } authors = pair_names(author_names) - author_email = random_author_email(author_details) - puts "Committing under #{author_email}" - passthrough_args = argv.map{|arg| "'#{arg}'"}.join(' ') + author_details = random_author_details(author_details) + author_email = author_details[:email] + author_key = author_details[:key] env_variables = "GIT_AUTHOR_NAME='#{authors}' GIT_AUTHOR_EMAIL='#{author_email}' GIT_COMMITTER_NAME='#{authors}' GIT_COMMITTER_EMAIL='#{author_email}'" - system "#{env_variables} git commit #{passthrough_args}" + + puts "Committing under #{author_email}" + + unless author_key.nil? + argv << "--gpg-sign=#{author_key}" + puts "Signing with key #{author_key}" + end + + args = argv.map{|arg| "'#{arg}'"}.join(' ') + + system "#{env_variables} git commit #{args}" rescue GitPairException => e puts e.message exit 1 @@ -108,6 +118,8 @@ def parse_cli_options(argv) # include the following section to set custom email addresses for users #email_addresses: # zr: zach.robinson@example.com + #gpg_keys: + # zr: 1A2B3C4D By default this affects the current project (.git/config).
@@ -178,9 +190,9 @@ def build_email(emails, config) end end - def random_author_email(author_details) + def random_author_details(author_details) author_id = author_details.keys.sample - author_details[author_id][:email] + author_details[author_id] end def set_git_config(global, options) @@ -227,9 +239,12 @@ def extract_author_details_from_config(config, initials) email = read_custom_email_address_from_config(config, i) email ||= "#{email_id}@#{config['email']['domain']}" + key = read_gpg_keys_from_config(config, i) + details[i] = { :name => full_name, - :email => email + :email => email, + :key => key } end @@ -241,6 +256,11 @@ def read_custom_email_address_from_config(config, initial) return config['email_addresses'][initial.downcase] end + def read_gpg_keys_from_config(config, initial) + return nil unless config['gpg_keys'] + return config['gpg_keys'][initial.downcase] + end + private def pair_names(author_names) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 81016b3..e0d2559 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -345,6 +345,10 @@ def committer_email_of_last_commit (run "git log -1 --pretty=%ce").strip end + def committer_email_and_key_of_last_commit + (run "git log -1 --pretty='%ae %GK'").strip + end + it "makes a commit" do git_pair_commit output = run "git log -1" @@ -421,6 +425,62 @@ def committer_email_of_last_commit emails.should =~ ['abb@the-host.com', 'test@other-host.com'] end end + + context 'when gpg keys are configured' do + before do + run 'cat ../gpg-keys.asc | gpg --import >/dev/null 2>&1' + end + + after do + + end + + context 'when one of the pair has a key' do + before do + File.open('.pairs', 'a') do |pairs| + pairs.puts <<-YAML.unindent + email_addresses: + ab: abb@other-host.com + bc: bcc@other-host.com + gpg_keys: + ab: 54E416F1 + YAML + end + + run 'git pair ab bc' + end + + it 'uses that key with corresponding email' do + keys = 6.times.map do + git_pair_commit + committer_email_and_key_of_last_commit + end.uniq + + keys =~ ['abb@other-host.com 54E416F1'] + end + + context 'when both pairs have a key' do + before do + File.open('.pairs', 'a') do |pairs| + pairs.puts <<-YAML.unindent + bc: 4A000CE7 + YAML + end + + run 'git pair ab bc' + end + + it 'uses both keys corresponding emails' do + keys = 6.times.map do + git_pair_commit + committer_email_and_key_of_last_commit + end.uniq + + keys =~ ['abb@other-host.com 54E416F1', 'bcc@other-host.com 4A000CE7'] + end + end + end + end end context 'when no pair has been set' do diff --git a/spec/gpg-keys.asc b/spec/gpg-keys.asc new file mode 100644 index 0000000..16065b0 --- /dev/null +++ b/spec/gpg-keys.asc @@ -0,0 +1,100 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mI0EV3Rw9AEEAOYXwUh1oLgEjnlMHeOTOr6XoQSRK0rxM6Ff5vRM+rQjwvnnm+57 +pPi2QllY/b7LDUWQbjfy2yfdOLUQHgpI5MQM8BLMz/jmcKCzQCZD8lfd+I7Mnuk3 +lS1fAtNRviHpSLXOlE/wLm/QxnsERHIMFLdOdMQQcgcE/iHDjxf01KJbABEBAAG0 +GkFhIEJiIDxhYmJAb3RoZXItaG9zdC5jb20+iLgEEwECACIFAld0cPQCGwMGCwkI +BwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJENv7kh1U5BbxRLQD/0yPZ7VvhvxJOySA +7Ivpu09qdeM5MMClmMjl9aWp6KeMr1qC9v9B5dPQxVqJy3YBi2/MCEuGjeH9PydX +NItvzzDm+Obok7myt4PHb5RV4FGy5oFTp8qmEGO/kWe4Rupqe8CEXH0+hOa39eLS +ghY0yeaabPWKxmpG+g7bO0Y7W5kjuI0EV3Rw9AEEANdyt3JSJlWrruXA0tFJvAvm +uP60Cz5idDWqKpWNT4HDRamIYITdmgJ01o/o8WA8zOLbp7MSAeVMO146OXw8Z9UK +rLglJOhGc3JGnfOJEnC9W7I9+0v6DGW4sDi702AN2QE4Jm3LeqYlZ8a4rEM0QST7 +Bohxa3Ug1DWg9lTyVROlABEBAAGInwQYAQIACQUCV3Rw9AIbDAAKCRDb+5IdVOQW +8VyWA/44JU4d6p0aNo1j1XdUbRgSo/up7uPPGS0D8y0dNwjT/E+ln3QSCKOdtzfo +G1cLrr2Q8/XgDlYeAGWNPbC6pYREMoKpR5gYrC8/5VxpF4zhIvh5r8nBoIGKM+IZ +QRMYGBi+1yEKvxxpXOMrku5HbQ8yhHhZB849okyofj9on2c2Bw== +=q2u7 +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQHYBFd0cPQBBADmF8FIdaC4BI55TB3jkzq+l6EEkStK8TOhX+b0TPq0I8L555vu +e6T4tkJZWP2+yw1FkG438tsn3Ti1EB4KSOTEDPASzM/45nCgs0AmQ/JX3fiOzJ7p +N5UtXwLTUb4h6Ui1zpRP8C5v0MZ7BERyDBS3TnTEEHIHBP4hw48X9NSiWwARAQAB +AAP+Lvx03N4gZtOPYJe5lspu+ZKvL+aRJ6mfuHmECSlbHMQcwbmZLxcStjNJ00MH +9hky6Zy31TcDp91WAit7ZvBBvqAUTHDHmfoXR06nb6n90XaTi/m9TDylXFL/TNP+ +L36WOSKfKut2iBfQXfchHi2JaQJwzABbQBhPAuSy3erJCfkCAOrMQBPqYUOFQ19u +psR0QRc9mRdPGsgE/ldlGFpoOQkdOTgZyghjaNYZhkLJI51e12jtvBJV2CHOJ2JG +rwKcVwcCAPrevUIgK1DypR5vV6UIdSZkmiIrD35lTDG5xsNTAwxTDNwZ+E1qW+xg +rMPLbknWjh/CUmaHctJynmU6W5ANUQ0B+gJbfTXNUiVVfSEaUOd8P1XTm/DJwQly +vGVlp71a5gnnPunatnuIGRbVGwQo5LyVfW9/sXYdS7Hg27RZ/j+sPs2Wi7QaQWEg +QmIgPGFiYkBvdGhlci1ob3N0LmNvbT6IuAQTAQIAIgUCV3Rw9AIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQ2/uSHVTkFvFEtAP/TI9ntW+G/Ek7JIDsi+m7 +T2p14zkwwKWYyOX1panop4yvWoL2/0Hl09DFWonLdgGLb8wIS4aN4f0/J1c0i2/P +MOb45uiTubK3g8dvlFXgUbLmgVOnyqYQY7+RZ7hG6mp7wIRcfT6E5rf14tKCFjTJ +5pps9YrGakb6Dts7RjtbmSOdAdgEV3Rw9AEEANdyt3JSJlWrruXA0tFJvAvmuP60 +Cz5idDWqKpWNT4HDRamIYITdmgJ01o/o8WA8zOLbp7MSAeVMO146OXw8Z9UKrLgl +JOhGc3JGnfOJEnC9W7I9+0v6DGW4sDi702AN2QE4Jm3LeqYlZ8a4rEM0QST7Bohx +a3Ug1DWg9lTyVROlABEBAAEAA/sFiY9DD7vbsjpTV8dgInlqabDet8xQlPTQd3uT +G6F4syCHoPFKH1MlnDcl77v0cahnOqbVKJgf4Pu0CkiowF/l9i0vH58O/JQKdbpE +8VNajRFHslifr+Bzm/iL7Si0PBRkpIzMYlKFT+Yynic96wQ1MeBMq8yOkEV/9enE +nhnHaQIA6Cf6p68yG2MJJgVFcd1lwIiII5PXtD22ut7nNhq+DIzrpzNfi4KGU2+F +VJzMAH2GZe4UECZxJetsNlzmAA8SNwIA7ZNv2zxpr1DBIVYxKVbc16UmROke9vAD ++hXoo1pvTlkqo8I3574PxIxUbTNiMHZRuiJ2jbSEESZlUYhzxNyLAwIAiyGji4LR +loPG1xVMBXcJ3pvAnn5WoTGdM+bBoDS1GYA319OsKisr/QdiGNlXlGwZ/wtyEMF/ +NGhjVYSGO4RVQZmhiJ8EGAECAAkFAld0cPQCGwwACgkQ2/uSHVTkFvFclgP+OCVO +HeqdGjaNY9V3VG0YEqP7qe7jzxktA/MtHTcI0/xPpZ90Egijnbc36BtXC669kPP1 +4A5WHgBljT2wuqWERDKCqUeYGKwvP+VcaReM4SL4ea/JwaCBijPiGUETGBgYvtch +Cr8caVzjK5LuR20PMoR4WQfOPaJMqH4/aJ9nNgc= +=1pXE +-----END PGP PRIVATE KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mI0EV3RxJgEEANIbuxlsiCqvaUZpt+wyeqi5R4WQn6xuh8gXBZo+bhZhKefA1hr1 +2ZV4hakBmEs4fk+FJ4BhiRECZ5sXEwOLN4q6uocqt6JXZmDSRFAHlGBlyjl5bP9U +ZpkzkUXjN5wmTGvei6E304JFHnb/RyR9bAdhXUDnDqgR1u6v+hJn4eMhABEBAAG0 +GkJiIENjIDxiY2NAb3RoZXItaG9zdC5jb20+iLgEEwECACIFAld0cSYCGwMGCwkI +BwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEEXx+iVKAAznYxgEAMUZN+25tEaOd1wn +uNIaXCdBGBS4trf34n14OGbky9eh96X3FAKOt0nJ6xZULLbqD1OpWIU8NugstXAw +XoFTTYHK4Cm0pRtCLKnnrmg6G1uo+wrzlnpCziCzGKu91vCdtk/1Hm80eNUSyXRJ +O1lkI/0l0GKsRfUYLcpeJa7PrtcFuI0EV3RxJgEEAMGPBWnD5HLZtvmfDfBnnjhl +yU9ClRDdPNELJ+c5dRZTjkbJYVHaMGO+EH1ErGC1I5S/4vyiBC/MMK2GZzqzxZpF +Rkj3dnZSQutcEDss2p6oHZ/j9GZhZPD10fSDthym2grbMtRZ9LMpF6jq/lngzDZQ +B2jKk4KE+LgR4oExWD/vABEBAAGInwQYAQIACQUCV3RxJgIbDAAKCRBF8folSgAM +5wb6BADEiYHDrtiuOEFnfAKDm+rTbp2jR8eCIC5Jlx0Klc0cg3jKX+1+ye5Tqq2y +q47zLAVidc7FPxAJdBeUCNhGwX1RdsJ9T3u7+7N7U6bKnaE4hWFTIQnFMZmCkYY5 +7Cm1wO7fb7bR63lYUqqo2iuv/LTzMA51zIvden6wcHUtjQJf5Q== +=mDht +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQHYBFd0cSYBBADSG7sZbIgqr2lGabfsMnqouUeFkJ+sbofIFwWaPm4WYSnnwNYa +9dmVeIWpAZhLOH5PhSeAYYkRAmebFxMDizeKurqHKreiV2Zg0kRQB5RgZco5eWz/ +VGaZM5FF4zecJkxr3ouhN9OCRR52/0ckfWwHYV1A5w6oEdbur/oSZ+HjIQARAQAB +AAP+IHwuoafs5rKfw4YBbJjCa7dX1lANy/576mUa1eYMpdOog79GKz1zQn+zpLWN +KyYlK1zSRnBuHY3iYHGBHFVoRPgyLzVnP3fmktiMdoDY84hiDICCfYNzSQoPhSC7 +0LgyI0c9q4thlv6pRzrlZs+Q6qZ/XtZ4VbzLyn7SI5i2D4UCANqosv6BXGPg2CEg +4lj4NJj6VwSbJbz7qSBO5PjMGROYTdopI3S9+exg7FNxrY2z7oNERT+8zS4znl38 +K+AOjS0CAPX9NxzvMCz8I4Xlgoe4/qZqAgkd688K+G3YFEta+9tIbw5ymlXEXeop +tWOn5QcbwRZ82HbJ0zsQvxI6Ef1O7kUCAPHsIHEXCcNAImf5k+USRzbPsyhS7FWv +F48RV2f412/MG1kn10JyX3KsetcUS1Mg8C/qHFRR69hoRUk25hq8tCiga7QaQmIg +Q2MgPGJjY0BvdGhlci1ob3N0LmNvbT6IuAQTAQIAIgUCV3RxJgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQRfH6JUoADOdjGAQAxRk37bm0Ro53XCe40hpc +J0EYFLi2t/fifXg4ZuTL16H3pfcUAo63ScnrFlQstuoPU6lYhTw26Cy1cDBegVNN +gcrgKbSlG0IsqeeuaDobW6j7CvOWekLOILMYq73W8J22T/UebzR41RLJdEk7WWQj +/SXQYqxF9Rgtyl4lrs+u1wWdAdgEV3RxJgEEAMGPBWnD5HLZtvmfDfBnnjhlyU9C +lRDdPNELJ+c5dRZTjkbJYVHaMGO+EH1ErGC1I5S/4vyiBC/MMK2GZzqzxZpFRkj3 +dnZSQutcEDss2p6oHZ/j9GZhZPD10fSDthym2grbMtRZ9LMpF6jq/lngzDZQB2jK +k4KE+LgR4oExWD/vABEBAAEAA/sHNWmHm3R+C26GPPpGa9qXhkzAikDF+yahSBV9 +l2ItXdMviogES7QFv0/3/gJCCFLQO+eg7jkMscGzQo1QHlMOeHMQB9Nw2qXa4Vzx +Zs7jVVTVKo1GyCD28/aOhcD9Cip+/31trjqBJ5HwqgZ77kuxv1BDbSRQdXpgk0vH +dREIPQIAyLjs/0QB0bmR/9+CbEn/dkZDTmQPsBYybTuPJP2l4KJjRdT4CZLJQHeo +XvH2AURFAR1GYbNbB1ggZ6FhlzSrdQIA9t0Myw1MJUAggQTGmqIL52OVWAMRE/4f +Rz5EAMzByfOMUJupq+nHyOH1q9iobJe+Ca9Jtpk/DyTBifD4OrHlUwIA9q7xVN9k +WnAtNQd8wJ7xMvTgYXuW16htskeSXIFCCAdiFV6FCx0AwSJGX6D4yAsrCuIOuito +J8zuU4yA9lqNGZsqiJ8EGAECAAkFAld0cSYCGwwACgkQRfH6JUoADOcG+gQAxImB +w67YrjhBZ3wCg5vq026do0fHgiAuSZcdCpXNHIN4yl/tfsnuU6qtsquO8ywFYnXO +xT8QCXQXlAjYRsF9UXbCfU97u/uze1Omyp2hOIVhUyEJxTGZgpGGOewptcDu32+2 +0et5WFKqqNorr/y08zAOdcyL3Xp+sHB1LY0CX+U= +=qdTI +-----END PGP PRIVATE KEY BLOCK-----