<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="Asciidoctor 1.5.2"> <meta name="author" content="Tristan Juricek"> <title>Perforce Web Services Guide: Internal Alpha</title> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400"> <style> /* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ /* Remove the comments around the @import statement below when using this as a custom stylesheet */ /*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400";*/ article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} audio,canvas,video{display:inline-block} audio:not([controls]){display:none;height:0} [hidden],template{display:none} script{display:none!important} html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} body{margin:0} a{background:transparent} a:focus{outline:thin dotted} a:active,a:hover{outline:0} h1{font-size:2em;margin:.67em 0} abbr[title]{border-bottom:1px dotted} b,strong{font-weight:bold} dfn{font-style:italic} hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} mark{background:#ff0;color:#000} code,kbd,pre,samp{font-family:monospace;font-size:1em} pre{white-space:pre-wrap} q{quotes:"\201C" "\201D" "\2018" "\2019"} small{font-size:80%} sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} sup{top:-.5em} sub{bottom:-.25em} img{border:0} svg:not(:root){overflow:hidden} figure{margin:0} fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} legend{border:0;padding:0} button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} button,input{line-height:normal} button,select{text-transform:none} button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} button[disabled],html input[disabled]{cursor:default} input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} textarea{overflow:auto;vertical-align:top} table{border-collapse:collapse;border-spacing:0} *,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} html,body{font-size:100%} body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto} a:hover{cursor:pointer} img,object,embed{max-width:100%;height:auto} object,embed{height:100%} img{-ms-interpolation-mode:bicubic} #map_canvas img,#map_canvas embed,#map_canvas object,.map_canvas img,.map_canvas embed,.map_canvas object{max-width:none!important} .left{float:left!important} .right{float:right!important} .text-left{text-align:left!important} .text-right{text-align:right!important} .text-center{text-align:center!important} .text-justify{text-align:justify!important} .hide{display:none} .antialiased,body{-webkit-font-smoothing:antialiased} img{display:inline-block;vertical-align:middle} textarea{height:auto;min-height:50px} select{width:100%} p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6} .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} a{color:#2156a5;text-decoration:underline;line-height:inherit} a:hover,a:focus{color:#1d4b8f} a img{border:none} p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} p aside{font-size:.875em;line-height:1.35;font-style:italic} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} h1{font-size:2.125em} h2{font-size:1.6875em} h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} h4,h5{font-size:1.125em} h6{font-size:1em} hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} em,i{font-style:italic;line-height:inherit} strong,b{font-weight:bold;line-height:inherit} small{font-size:60%;line-height:inherit} code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em} ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} ul.square{list-style-type:square} ul.circle{list-style-type:circle} ul.disc{list-style-type:disc} ul.no-bullet{list-style:none} ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} dl dt{margin-bottom:.3125em;font-weight:bold} dl dd{margin-bottom:1.25em} abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} abbr{text-transform:none} blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} blockquote cite:before{content:"\2014 \0020"} blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} @media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} h1{font-size:2.75em} h2{font-size:2.3125em} h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} h4{font-size:1.4375em}}table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} table thead,table tfoot{background:#f7f8f7;font-weight:bold} table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} .clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table} .clearfix:after,.float-group:after{clear:both} *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed} pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} .keyseq{color:rgba(51,51,51,.8)} kbd{display:inline-block;color:rgba(0,0,0,.8);font-size:.75em;line-height:1.4;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:-.15em .15em 0 .15em;padding:.2em .6em .2em .5em;vertical-align:middle;white-space:nowrap} .keyseq kbd:first-child{margin-left:0} .keyseq kbd:last-child{margin-right:0} .menuseq,.menu{color:rgba(0,0,0,.8)} b.button:before,b.button:after{position:relative;top:-1px;font-weight:400} b.button:before{content:"[";padding:0 3px 0 2px} b.button:after{content:"]";padding:0 2px 0 3px} p a>code:hover{color:rgba(0,0,0,.9)} #header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} #header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table} #header:after,#content:after,#footnotes:after,#footer:after{clear:both} #content{margin-top:1.25em} #content:before{content:none} #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} #header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} #header .details span:first-child{margin-left:-.125em} #header .details span.email a{color:rgba(0,0,0,.85)} #header .details br{display:none} #header .details br+span:before{content:"\00a0\2013\00a0"} #header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} #header .details br+span#revremark:before{content:"\00a0|\00a0"} #header #revnumber{text-transform:capitalize} #header #revnumber:after{content:"\00a0"} #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} #toc{border-bottom:1px solid #efefed;padding-bottom:.5em} #toc>ul{margin-left:.125em} #toc ul.sectlevel0>li>a{font-style:italic} #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} #toc a{text-decoration:none} #toc a:active{text-decoration:underline} #toctitle{color:#7a2518;font-size:1.2em} @media only screen and (min-width:768px){#toctitle{font-size:1.375em} body.toc2{padding-left:15em;padding-right:0} #toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} #toc.toc2 #toctitle{margin-top:0;font-size:1.2em} #toc.toc2>ul{font-size:.9em;margin-bottom:0} #toc.toc2 ul ul{margin-left:0;padding-left:1em} #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} body.toc2.toc-right{padding-left:0;padding-right:15em} body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} #toc.toc2{width:20em} #toc.toc2 #toctitle{font-size:1.375em} #toc.toc2>ul{font-size:.95em} #toc.toc2 ul ul{padding-left:1.25em} body.toc2.toc-right{padding-left:0;padding-right:20em}}#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} #content #toc>:first-child{margin-top:0} #content #toc>:last-child{margin-bottom:0} #footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} #footer-text{color:rgba(255,255,255,.8);line-height:1.44} .sect1{padding-bottom:.625em} @media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}.sect1+.sect1{border-top:1px solid #efefed} #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} #content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} .audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0} .paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)} table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit} .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} .admonitionblock>table td.icon{text-align:center;width:80px} .admonitionblock>table td.icon img{max-width:none} .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} .exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} .exampleblock>.content>:first-child{margin-top:0} .exampleblock>.content>:last-child{margin-bottom:0} .sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} .sidebarblock>:first-child{margin-top:0} .sidebarblock>:last-child{margin-bottom:0} .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} .literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} .sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} .literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} .literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} @media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} .listingblock pre.highlightjs{padding:0} .listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} .listingblock pre.prettyprint{border-width:0} .listingblock>.content{position:relative} .listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} .listingblock:hover code[data-lang]:before{display:block} .listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999} .listingblock.terminal pre .command:not([data-prompt]):before{content:"$"} table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0} table.pyhltable td.code{padding-left:.75em;padding-right:0} pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} pre.pygments .lineno{display:inline-block;margin-right:.25em} table.pyhltable .linenodiv{background:none!important;padding-right:0!important} .quoteblock{margin:0 1em 1.25em 1.5em;display:table} .quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} .quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} .quoteblock blockquote{margin:0;padding:0;border:0} .quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} .quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} .quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} .quoteblock .quoteblock blockquote{padding:0 0 0 .75em} .quoteblock .quoteblock blockquote:before{display:none} .verseblock{margin:0 1em 1.25em 1em} .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} .verseblock pre strong{font-weight:400} .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} .quoteblock .attribution br,.verseblock .attribution br{display:none} .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.05em;color:rgba(0,0,0,.6)} .quoteblock.abstract{margin:0 0 1.25em 0;display:block} .quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0} .quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none} table.tableblock{max-width:100%;border-collapse:separate} table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0} table.spread{width:100%} table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0} table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0} table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0} table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0} table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0} table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0} table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0} table.frame-all{border-width:1px} table.frame-sides{border-width:0 1px} table.frame-topbot{border-width:1px 0} th.halign-left,td.halign-left{text-align:left} th.halign-right,td.halign-right{text-align:right} th.halign-center,td.halign-center{text-align:center} th.valign-top,td.valign-top{vertical-align:top} th.valign-bottom,td.valign-bottom{vertical-align:bottom} th.valign-middle,td.valign-middle{vertical-align:middle} table thead th,table tfoot th{font-weight:bold} tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} p.tableblock>code:only-child{background:none;padding:0} p.tableblock{font-size:1em} td>div.verse{white-space:pre} ol{margin-left:1.75em} ul li ol{margin-left:1.5em} dl dd{margin-left:1.125em} dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none} ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em} ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em} ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px} ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden} ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block} ul.inline>li>*{display:block} .unstyled dl dt{font-weight:400;font-style:normal} ol.arabic{list-style-type:decimal} ol.decimal{list-style-type:decimal-leading-zero} ol.loweralpha{list-style-type:lower-alpha} ol.upperalpha{list-style-type:upper-alpha} ol.lowerroman{list-style-type:lower-roman} ol.upperroman{list-style-type:upper-roman} ol.lowergreek{list-style-type:lower-greek} .hdlist>table,.colist>table{border:0;background:none} .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} td.hdlist1{padding-right:.75em;font-weight:bold} td.hdlist1,td.hdlist2{vertical-align:top} .literalblock+.colist,.listingblock+.colist{margin-top:-.5em} .colist>table tr>td:first-of-type{padding:0 .75em;line-height:1} .colist>table tr>td:last-of-type{padding:.25em 0} .thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} .imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} .imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} .imageblock>.title{margin-bottom:0} .imageblock.thumb,.imageblock.th{border-width:6px} .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} .image.left{margin-right:.625em} .image.right{margin-left:.625em} a.image{text-decoration:none} span.footnote,span.footnoteref{vertical-align:super;font-size:.875em} span.footnote a,span.footnoteref a{text-decoration:none} span.footnote a:active,span.footnoteref a:active{text-decoration:underline} #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0} #footnotes .footnote{padding:0 .375em;line-height:1.3;font-size:.875em;margin-left:1.2em;text-indent:-1.2em;margin-bottom:.2em} #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none} #footnotes .footnote:last-of-type{margin-bottom:0} #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} .gist .file-data>table td.line-data{width:99%} div.unbreakable{page-break-inside:avoid} .big{font-size:larger} .small{font-size:smaller} .underline{text-decoration:underline} .overline{text-decoration:overline} .line-through{text-decoration:line-through} .aqua{color:#00bfbf} .aqua-background{background-color:#00fafa} .black{color:#000} .black-background{background-color:#000} .blue{color:#0000bf} .blue-background{background-color:#0000fa} .fuchsia{color:#bf00bf} .fuchsia-background{background-color:#fa00fa} .gray{color:#606060} .gray-background{background-color:#7d7d7d} .green{color:#006000} .green-background{background-color:#007d00} .lime{color:#00bf00} .lime-background{background-color:#00fa00} .maroon{color:#600000} .maroon-background{background-color:#7d0000} .navy{color:#000060} .navy-background{background-color:#00007d} .olive{color:#606000} .olive-background{background-color:#7d7d00} .purple{color:#600060} .purple-background{background-color:#7d007d} .red{color:#bf0000} .red-background{background-color:#fa0000} .silver{color:#909090} .silver-background{background-color:#bcbcbc} .teal{color:#006060} .teal-background{background-color:#007d7d} .white{color:#bfbfbf} .white-background{background-color:#fafafa} .yellow{color:#bfbf00} .yellow-background{background-color:#fafa00} span.icon>.fa{cursor:default} .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} .admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c} .admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} .admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900} .admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400} .admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000} .conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} .conum[data-value] *{color:#fff!important} .conum[data-value]+b{display:none} .conum[data-value]:after{content:attr(data-value)} pre .conum[data-value]{position:relative;top:-.125em} b.conum *{color:inherit!important} .conum:not([data-value]):empty{display:none} h1,h2{letter-spacing:-.01em} dt,th.tableblock,td.content{text-rendering:optimizeLegibility} p,td.content{letter-spacing:-.01em} p strong,td.content strong{letter-spacing:-.005em} p,blockquote,dt,td.content{font-size:1.0625rem} p{margin-bottom:1.25rem} .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} .exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} .print-only{display:none!important} @media print{@page{margin:1.25cm .75cm} *{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} a{color:inherit!important;text-decoration:underline!important} a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} abbr[title]:after{content:" (" attr(title) ")"} pre,blockquote,tr,img{page-break-inside:avoid} thead{display:table-header-group} img{max-width:100%!important} p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} #toc,.sidebarblock,.exampleblock>.content{background:none!important} #toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important} .sect1{padding-bottom:0!important} .sect1+.sect1{border:0!important} #header>h1:first-child{margin-top:1.25rem} body.book #header{text-align:center} body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0} body.book #header .details{border:0!important;display:block;padding:0!important} body.book #header .details span:first-child{margin-left:0!important} body.book #header .details br{display:block} body.book #header .details br+span:before{content:none!important} body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} .listingblock code[data-lang]:before{display:block} #footer{background:none!important;padding:0 .9375em} #footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em} .hide-on-print{display:none!important} .print-only{display:block!important} .hide-for-print{display:none!important} .show-for-print{display:inherit!important}} </style> </head> <body class="article toc2 toc-right"> <div id="header"> <h1>Perforce Web Services Guide: Internal Alpha</h1> <div class="details"> <span id="author" class="author">Tristan Juricek</span><br> <span id="email" class="email"><a href="mailto:tjuricek@perforce.com">tjuricek@perforce.com</a></span><br> <span id="revnumber">version 2015.1.alpha,</span> <span id="revdate">May 2015</span> </div> <div id="toc" class="toc2"> <div id="toctitle">Table of Contents</div> <ul class="sectlevel1"> <li><a href="#_about_this_manual">About This Manual</a> <ul class="sectlevel2"> <li><a href="#_please_give_us_feedback">Please give us feedback</a></li> </ul> </li> <li><a href="#_overview">Overview</a> <ul class="sectlevel2"> <li><a href="#_release_compatibility_of_the_api">Release compatibility of the API</a></li> <li><a href="#_purpose_of_the_api">Purpose of the API</a></li> <li><a href="#_architecture_of_the_api">Architecture of the API</a></li> </ul> </li> <li><a href="#_deploying_web_services">Deploying Web Services</a></li> <li><a href="#_application_programming">Application Programming</a> <ul class="sectlevel2"> <li><a href="#_perforce_web_api_content_types">Perforce Web API Content Types</a></li> <li><a href="#_perforce_web_api_authentication">Perforce Web API Authentication</a></li> <li><a href="#_accessing_the_perforce_web_api_using_a_perforce_ticket">Accessing the Perforce Web API using a Perforce ticket</a></li> <li><a href="#_accessing_the_perforce_web_api_using_a_session_token">Accessing the Perforce Web API using a session token</a></li> </ul> </li> <li><a href="#_http_protocol_reference">HTTP Protocol Reference</a> <ul class="sectlevel2"> <li><a href="#_p4_web_api_http_protocol">P4 Web API HTTP Protocol</a></li> </ul> </li> <li><a href="#_client_sdk_reference">Client SDK Reference</a> <ul class="sectlevel3"> <li><a href="#_qt_sdk_for_phoenix_services">Qt SDK for Phoenix Services</a></li> </ul> </li> </ul> </div> </div> <div id="content"> <div class="sect1"> <h2 id="_about_this_manual"><a class="link" href="#_about_this_manual">About This Manual</a></h2> <div class="sectionbody"> <div class="paragraph"> <p>This guide covers the Perforce Web Services, a system of microservices that are used by Perforce products for centralized management of common concepts. The guide details usage by client applications and other services at both the HTTP protocol and client SDK levels.</p> </div> <div class="sect2"> <h3 id="_please_give_us_feedback"><a class="link" href="#_please_give_us_feedback">Please give us feedback</a></h3> <div class="paragraph"> <p>If you have any feedback for us, or detect any errors in this guide, please email details to <a href="mailto:manual@perforce.com">manual@perforce.com</a>.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_overview"><a class="link" href="#_overview">Overview</a></h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_release_compatibility_of_the_api"><a class="link" href="#_release_compatibility_of_the_api">Release compatibility of the API</a></h3> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> This section is obsolete </td> </tr> </table> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> TODO Rewrite in context of web services </td> </tr> </table> </div> <div class="paragraph"> <p>The Perforce Web API is subject to change from release to release, and is not guaranteed to support the exact same methods from one release to the next. However, applications that you create using the Web API can run against previous releases of Perforce and will probably run against later releases of Perforce.</p> </div> <div class="paragraph"> <p>Support for specific features depends on the version of Perforce and the API that you use.</p> </div> </div> <div class="sect2"> <h3 id="_purpose_of_the_api"><a class="link" href="#_purpose_of_the_api">Purpose of the API</a></h3> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> This section is obsolete </td> </tr> </table> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> TODO Rewrite in context of web services </td> </tr> </table> </div> <div class="paragraph"> <p>The Perforce Web API enables you to create applications that interact with end users, send commands to the Perforce server and process data returned from the versioning service. The API is a programmatic interface, and does not send commands directly to the server.</p> </div> <div class="paragraph"> <p>Not all Perforce commands are supported by the Web API. Commands that operate on the user’s client workspace are generally not supported. In general, you can not submit or alter files on behalf of a user with the Perforce Web API. You can, however, create branches, edit workspace metadata, and other operations that can establish custom workflow or automate administrative tasks.</p> </div> </div> <div class="sect2"> <h3 id="_architecture_of_the_api"><a class="link" href="#_architecture_of_the_api">Architecture of the API</a></h3> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> This section is obsolete </td> </tr> </table> </div> <div class="admonitionblock note"> <table> <tr> <td class="icon"> <div class="title">Note</div> </td> <td class="content"> TODO Rewrite in context of web services </td> </tr> </table> </div> <div class="paragraph"> <p>The Perforce Web API is intended to be executed in a web server or integrated into another web application. Once available, it provides HTTP access to executing Perforce commands. Each HTTP method is stateless, except for authentication methods that use a stored token.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_deploying_web_services"><a class="link" href="#_deploying_web_services">Deploying Web Services</a></h2> <div class="sectionbody"> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> This is a preliminary mechanism for deploying a new system for QA purposes only. Yes, it will get replaced by another mechanism in the future. </td> </tr> </table> </div> <div class="paragraph"> <p>The following steps should be run on an Ubuntu 12 machine (with access to the internal Perforce infrastructure):</p> </div> <div class="literalblock"> <div class="content"> <pre># if you need curl run this: sudo apt-get install curl -y curl -L https://swarm.workshop.perforce.com/projects/perforce-software-helix-web-services/view/main/bootstrap/hws-bootstrap.sh -o hws-bootstrap.sh sudo bash hws-bootstrap.sh</pre> </div> </div> <div class="paragraph"> <p>Now test you can have access to the API:</p> </div> <div class="literalblock"> <div class="content"> <pre>session_id=`curl --data 'user=super&password=superuser1A!' http://localhost/p4_web_api/v1/sessions` curl --basic --user super:$session_id http://localhost/p4_web_api/v1/depots</pre> </div> </div> <div class="paragraph"> <p>You should see JSON indicating at least one depot exists:</p> </div> <div class="literalblock"> <div class="content"> <pre>[{"Depot":"depot","Date":1432236717,"Type":"local","Map":"depot/...","Description":"Default depot"}]</pre> </div> </div> </div> </div> <div class="sect1"> <h2 id="_application_programming"><a class="link" href="#_application_programming">Application Programming</a></h2> <div class="sectionbody"> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <div class="title">Warning</div> </td> <td class="content"> THIS SECTION IS OBSOLETE It has not been updated since we’ve added other services on top of the P4 Web API. </td> </tr> </table> </div> <div class="sect2"> <h3 id="_perforce_web_api_content_types"><a class="link" href="#_perforce_web_api_content_types">Perforce Web API Content Types</a></h3> <div class="paragraph"> <p>Almost all methods and return values send Content-Type as application/json. In the documentation, while we do accept application/x-www-form-urlencoded for most request bodies, we standardize on JSON for requests and responses.</p> </div> <div class="paragraph"> <p>When you see a documented request <code>form</code> field, you can interchange this with a form field or as a parameter of a JSON object sent in on input.</p> </div> </div> <div class="sect2"> <h3 id="_perforce_web_api_authentication"><a class="link" href="#_perforce_web_api_authentication">Perforce Web API Authentication</a></h3> <div class="paragraph"> <p>Perforce Web API methods require authentication as a Perforce user. Authentication uses the HTTP Basic Access Authentication scheme, except, the password of the user in the access header is either a Perforce ticket or a Perforce Web API session token.</p> </div> <div class="paragraph"> <p>The Perforce ticket approach may be convenient when you need to reuse the ticket for more than one API. For example, you may want to use the Perforce Web API for administrative operations, and then handle some logic that submits files for a client with the C++ API. The Perforce ticket approach, however, is less secure than the Perforce Web API session token, because the Perforce ticket can be obtained in via each method request.</p> </div> <div class="paragraph"> <p>For cases where you will only use the Perforce Web API, the session token method is likely more secure. Here, you will let the Perforce Web API generate a random session token that will be reused to subsequent calls. This session token is only valid with that instance of the Perforce Web API, and can not be reused with any other Perforce API.</p> </div> </div> <div class="sect2"> <h3 id="_accessing_the_perforce_web_api_using_a_perforce_ticket"><a class="link" href="#_accessing_the_perforce_web_api_using_a_perforce_ticket">Accessing the Perforce Web API using a Perforce ticket</a></h3> <div class="paragraph"> <p>When you have a Perforce ticket for the user, you can use the ticket as the password for the Basic Authentication scheme to any command.</p> </div> <div class="paragraph"> <p>For example, say the user jdoe has signed in and obtained the P4 ticket <code>09899EBAD658FC3C41B425CA67E6F7CA</code>. (This ticket can be obtained via the command p4 login -p.) The header for this ticket would look like <code>Authorization: Basic amRvZTowOTg5OUVCQUQ2NThGQzNDNDFCNDI1Q0E2N0U2RjdDQQ==</code>.</p> </div> <div class="paragraph"> <p>This can be used in cases where your current application obtains and stores p4 tickets, which avoids having to create a P4 session below.</p> </div> <div class="paragraph"> <p>Please note this will not work for host-locked tickets where the host is running on a different machine from the P4 Web API. The Perforce host connection should use the same IP address for the P4 Web API as the command that actually created the Perforce ticket.</p> </div> </div> <div class="sect2"> <h3 id="_accessing_the_perforce_web_api_using_a_session_token"><a class="link" href="#_accessing_the_perforce_web_api_using_a_session_token">Accessing the Perforce Web API using a session token</a></h3> <div class="paragraph"> <p>You can also use the P4 Web API to generate session tokens that are only valid via the P4 Web API, which can be more secure.</p> </div> <div class="paragraph"> <p>Sessions are created via the <code>POST /v1/sessions</code> command. The result of this command is a GUID that can only be used by this P4 Web API server. Use this GUID as the password in the Basic Authentication scheme for any other command.</p> </div> <div class="paragraph"> <p>For example, say you receive the session ID <code>561547ba-6938-4b50-8a76-aca4849924c5</code> for the user jdoe. Your authorization header would look like <code>Authorization: Basic amRvZTo1NjE1NDdiYS02OTM4LTRiNTAtOGE3Ni1hY2E0ODQ5OTI0YzU=</code>.</p> </div> <div class="paragraph"> <p>This session ID is associated with a Perforce ticket. When that underlying ticket is invalidated, you will start to receive 403 Forbidden errors from various commands. At that point you should regenerate a new session.</p> </div> <div class="paragraph"> <p>Note that you can also delete the session ID using the <code>DELETE /v1/sessions</code> command. For a web application, it may make sense to tye the underlying Perforce Web API session with your application’s session management.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_http_protocol_reference"><a class="link" href="#_http_protocol_reference">HTTP Protocol Reference</a></h2> <div class="sectionbody"> <div class="paragraph"> <p>Each section includes methods related to a particular topic or resource.</p> </div> <div class="sect2"> <h3 id="_p4_web_api_http_protocol"><a class="link" href="#_p4_web_api_http_protocol">P4 Web API HTTP Protocol</a></h3> <div class="paragraph"> <p>The P4 Web API is our HTTP based abstraction on top of core Perforce server concepts. Most Perforce command methods are represented here. The main difference is that commands that rely on client workspaces, which includes a lot of the 'manipulation' commands.</p> </div> <div class="ulist"> <ul> <li> <p><a href="#_p4_web_api_branches_http_protocol">P4 Web API Branches HTTP Protocol</a></p> </li> </ul> </div> <div class="sect3"> <h4 id="_p4_web_api_branches_http_protocol"><a class="link" href="#_p4_web_api_branches_http_protocol">P4 Web API Branches HTTP Protocol</a></h4> <div class="paragraph"> <p>These methods allow you to list, edit, and maintain branch specifications in your Perforce server.</p> </div> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 50%;"> <col style="width: 50%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Path</th> <th class="tableblock halign-left valign-top">Description</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#__code_get_v1_branches_code"><code>GET /v1/branches</code></a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">List available branches</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#__code_post_v1_branches_code"><code>POST /v1/branches</code></a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Create a new branch specification</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#__code_get_v1_branches_branch_code"><code>GET /v1/branches/[branch]</code></a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Describe a single branch specification</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#__code_patch_v1_branches_branch_code"><code>PATCH /v1/branches/[branch]</code></a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Update a branch specification</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#__code_delete_v1_branches_branch_code"><code>DELETE /v1/branches/[branch]</code></a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Delete a branch specification</p></td> </tr> </tbody> </table> <div class="sect4"> <h5 id="__code_get_v1_branches_code"><a class="link" href="#__code_get_v1_branches_code"><code>GET /v1/branches</code></a></h5> <div class="paragraph"> <p>Lists available branches in the system.</p> </div> <div class="paragraph"> <p>The resources of this list are summaries of branches in the system. For more details of each branch, append the <code>branch</code> property the end of this URL.</p> </div> <div class="paragraph"> <p>There are no other parameters to this method.</p> </div> <div class="paragraph"> <p>This method requires authentication. See <a href="#_perforce_web_api_authentication">Perforce Web API Authentication</a></p> </div> <div class="sect5"> <h6 id="_response_data"><a class="link" href="#_response_data">Response Data</a></h6> <div class="paragraph"> <p>Returns the result of the <code>p4 -ztag branches</code> command. For more field information refer to the command reference.</p> </div> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 25%;"> <col style="width: 25%;"> <col style="width: 25%;"> <col style="width: 25%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Parameter</th> <th class="tableblock halign-left valign-top">Description</th> <th class="tableblock halign-left valign-top">Type</th> <th class="tableblock halign-left valign-top">Required</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The branch name and primary ID</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Owner</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The Perforce login of the user that owns this branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Options</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The options of the branch specification</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Description</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The branch description</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Update</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The date the branch mapping was last changed.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Access</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The date the branch mapping was last accessed.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> </tbody> </table> </div> <div class="sect5"> <h6 id="_example"><a class="link" href="#_example">Example</a></h6> <div class="paragraph"> <p>Our standard authenticated request format for listing branches:</p> </div> <div class="literalblock"> <div class="content"> <pre>GET /v1/branches HTTP/1.1 Authorization: Basic c3VwZXI6NzcxMmJkMTAtOGQxMi00ZmUwLTgxM2MtZmM2OTExODQ3Yjdj</pre> </div> </div> <div class="paragraph"> <p>Here’s an example of a list with two branches in the response:</p> </div> <div class="literalblock"> <div class="content"> <pre>HTTP/1.1 200 OK Content-Type: application/json</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>[{ "Branch": "yagg-main", "Update": 1410907712, "Access": 1410907712, "Owner": "super", "Options": "unlocked", "Description": "Maintains a path from a development area to a main area.\n" }, { "Branch": "secondary-dev", "Update": 1410907541, "Access": 1410907111, "Owner": "jdoe", "Options": "unlocked", "Description": "Updates project Secondary's development area.\n" }]</pre> </div> </div> </div> </div> <div class="sect4"> <h5 id="__code_post_v1_branches_code"><a class="link" href="#__code_post_v1_branches_code"><code>POST /v1/branches</code></a></h5> <div class="paragraph"> <p>Creates a new branch specification.</p> </div> <div class="paragraph"> <p>Upon success, this will return a 303 redirect to the new branch specification resource that has been created.</p> </div> <div class="paragraph"> <p>If the branch already exists, this method will replace the existing branch completely.</p> </div> <div class="paragraph"> <p>This method requires authentication. See <a href="#_perforce_web_api_authentication">Perforce Web API Authentication</a>.</p> </div> <div class="sect5"> <h6 id="_parameters"><a class="link" href="#_parameters">Parameters</a></h6> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Parameter</th> <th class="tableblock halign-left valign-top">Description</th> <th class="tableblock halign-left valign-top">Type</th> <th class="tableblock halign-left valign-top">Parameter Type</th> <th class="tableblock halign-left valign-top">Required</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The name of the branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Owner</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The Perforce login of the user that owns the branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Description</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">A textual description of this branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">View</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">How different paths in the depot should relate to each other. Each string in the array contains a source and target end of the mapping. See the user guide for more information.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> </tbody> </table> </div> <div class="sect5"> <h6 id="_example_2"><a class="link" href="#_example_2">Example</a></h6> <div class="paragraph"> <p>We’ll create a simple branch my-project-main that maps <code>//depot/main/my-project/…​</code> to <code>//depot/dev/my-project/…​</code>.</p> </div> <div class="literalblock"> <div class="content"> <pre>POST /v1/branches HTTP/1.1 Authorization: Basic c3VwZXI6NzcxMmJkMTAtOGQxMi00ZmUwLTgxM2MtZmM2OTExODQ3Yjdj Content-Type: application/json</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>{ "Branch": "my-project-main", "Description": "Branch my project from main to dev.\n", "View": ["//depot/main/my-project/... //depot/dev/my-project/..."] }</pre> </div> </div> <div class="paragraph"> <p>The return value should be a redirect to the details page of the new branch.</p> </div> <div class="literalblock"> <div class="content"> <pre>HTTP/1.1 303 Found Location: http://example.com/p4/v1/branches/my-project-main</pre> </div> </div> <div class="paragraph"> <p>You may need to recall that the URL returned by a 303 response should be accessed via GET, and not via POST.</p> </div> </div> </div> <div class="sect4"> <h5 id="__code_get_v1_branches_branch_code"><a class="link" href="#__code_get_v1_branches_branch_code"><code>GET /v1/branches/[branch]</code></a></h5> <div class="paragraph"> <p>Return branch details.</p> </div> <div class="paragraph"> <p>This method requires authentication. See <a href="#_perforce_web_api_authentication">Perforce Web API Authentication</a>.</p> </div> <div class="sect5"> <h6 id="_parameters_2"><a class="link" href="#_parameters_2">Parameters</a></h6> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Parameter</th> <th class="tableblock halign-left valign-top">Description</th> <th class="tableblock halign-left valign-top">Type</th> <th class="tableblock halign-left valign-top">Parameter Type</th> <th class="tableblock halign-left valign-top">Required</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The branch name.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> </tbody> </table> </div> <div class="sect5"> <h6 id="_response_data_2"><a class="link" href="#_response_data_2">Response Data</a></h6> <div class="paragraph"> <p>Returns the result of <code>p4 -ztag branch [branch name].</code> For more information, see the command reference. The main difference between the details and list view is the inclusion of the View field.</p> </div> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 25%;"> <col style="width: 25%;"> <col style="width: 25%;"> <col style="width: 25%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Parameter</th> <th class="tableblock halign-left valign-top">Description</th> <th class="tableblock halign-left valign-top">Type</th> <th class="tableblock halign-left valign-top">Required</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The name of the branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Owner</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The Perforce login of the user that owns the branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Description</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">A textual description of this branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">View</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">How different paths in the depot should relate to each other. Each string in the array contains a source and target end of the mapping. See the user guide for more information.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Update</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The date the branch mapping was last changed.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Access</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The date the branch mapping was last accessed.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">number</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> </tbody> </table> </div> <div class="sect5"> <h6 id="_example_3"><a class="link" href="#_example_3">Example</a></h6> <div class="paragraph"> <p>Here is an example request for the branch yagg-main. This is a fairly simple branch, containing only one view mapping.</p> </div> <div class="literalblock"> <div class="content"> <pre>GET /v1/branches/yagg-main HTTP/1.1 Authorization: Basic c3VwZXI6NzcxMmJkMTAtOGQxMi00ZmUwLTgxM2MtZmM2OTExODQ3Yjdj</pre> </div> </div> <div class="paragraph"> <p>And the typical JSON response:</p> </div> <div class="literalblock"> <div class="content"> <pre>HTTP/1.1 200 OK Content-Type: application/json</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>{ "Branch": "yagg-main", "Update": 1410907712, "Access": 1410907712, "Owner": "super", "Description": "Maintains a path from a development area to a main area.\n", "Options": "unlocked", "View": ["//depot/yagg/... //depot/main/yagg/..."] }</pre> </div> </div> </div> </div> <div class="sect4"> <h5 id="__code_patch_v1_branches_branch_code"><a class="link" href="#__code_patch_v1_branches_branch_code"><code>PATCH /v1/branches/[branch]</code></a></h5> <div class="paragraph"> <p>Update branch specifications. Only the specified parameters in the body will be changed.</p> </div> <div class="paragraph"> <p>This method requires authentication. See <a href="#_perforce_web_api_authentication">Perforce Web API Authentication</a>.</p> </div> <div class="sect5"> <h6 id="_parameters_3"><a class="link" href="#_parameters_3">Parameters</a></h6> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Parameter</th> <th class="tableblock halign-left valign-top">Description</th> <th class="tableblock halign-left valign-top">Type</th> <th class="tableblock halign-left valign-top">Parameter Type</th> <th class="tableblock halign-left valign-top">Required</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The name of the branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Owner</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The Perforce login of the user that owns the branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">Description</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">A textual description of this branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">View</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">How different paths in the depot should relate to each other. Each string in the array contains a source and target end of the mapping. See the user guide for more information.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td> </tr> </tbody> </table> </div> <div class="sect5"> <h6 id="_example_4"><a class="link" href="#_example_4">Example</a></h6> <div class="paragraph"> <p>Here we’ll update the description of the existing branch my-project-main.</p> </div> <div class="literalblock"> <div class="content"> <pre>PATCH /v1/branches/my-project-main HTTP/1.1 Authorization: Basic c3VwZXI6NzcxMmJkMTAtOGQxMi00ZmUwLTgxM2MtZmM2OTExODQ3Yjdj Content-Type: application/json</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>{ "Description": "The updated my-project-main description.\n" }</pre> </div> </div> <div class="paragraph"> <p>The response will only contain the normal HTTP status information.</p> </div> <div class="literalblock"> <div class="content"> <pre>HTTP/1.1 200 OK</pre> </div> </div> </div> </div> <div class="sect4"> <h5 id="__code_delete_v1_branches_branch_code"><a class="link" href="#__code_delete_v1_branches_branch_code"><code>DELETE /v1/branches/[branch]</code></a></h5> <div class="paragraph"> <p>Removes the branch specification.</p> </div> <div class="paragraph"> <p>This method requires authentication. See <a href="#_perforce_web_api_authentication">Perforce Web API Authentication</a>.</p> </div> <div class="sect5"> <h6 id="_parameters_4"><a class="link" href="#_parameters_4">Parameters</a></h6> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Parameter</th> <th class="tableblock halign-left valign-top">Description</th> <th class="tableblock halign-left valign-top">Type</th> <th class="tableblock halign-left valign-top">Parameter Type</th> <th class="tableblock halign-left valign-top">Required</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock">branch</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The branch name.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td> </tr> </tbody> </table> </div> <div class="sect5"> <h6 id="_example_5"><a class="link" href="#_example_5">Example</a></h6> <div class="paragraph"> <p>Delete the branch <code>my-project-main</code>:</p> </div> <div class="literalblock"> <div class="content"> <pre>DELETE /v1/branches/my-project-main HTTP/1.1 Authorization: Basic c3VwZXI6NzcxMmJkMTAtOGQxMi00ZmUwLTgxM2MtZmM2OTExODQ3Yjdj</pre> </div> </div> <div class="paragraph"> <p>The response will only contain the normal HTTP status information.</p> </div> <div class="literalblock"> <div class="content"> <pre>HTTP/1.1 200 OK</pre> </div> </div> <div class="paragraph"> <p>Changes Read and create changelists</p> </div> <div class="paragraph"> <p>Clients List and manage client specifications</p> </div> <div class="paragraph"> <p>Commands Execute generic Perforce methods</p> </div> <div class="paragraph"> <p>Depots List and manage depot specifications</p> </div> <div class="paragraph"> <p>Files File browsing and upload methods.</p> </div> <div class="paragraph"> <p>Groups List and manage group specifications</p> </div> <div class="paragraph"> <p>Jobs List and manage job specifications</p> </div> <div class="paragraph"> <p>Labels List and manage label specifications</p> </div> <div class="paragraph"> <p>Protections List and update system protections</p> </div> <div class="paragraph"> <p>Servers List and manage server specifications</p> </div> <div class="paragraph"> <p>Sessions Manage a Perforce Web API security token</p> </div> <div class="paragraph"> <p>Triggers List and update system triggers</p> </div> <div class="paragraph"> <p>Users Manage Perforce users</p> </div> </div> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="_client_sdk_reference"><a class="link" href="#_client_sdk_reference">Client SDK Reference</a></h2> <div class="sectionbody"> <div class="ulist"> <ul> <li> <p><a href="#_qt_sdk_for_phoenix_services">Qt SDK for Phoenix Services</a></p> </li> </ul> </div> <div class="sect3"> <h4 id="_qt_sdk_for_phoenix_services"><a class="link" href="#_qt_sdk_for_phoenix_services">Qt SDK for Phoenix Services</a></h4> <div class="paragraph"> <p>The Qt SDK for Phoenix Services provides source libraries for manipulating project metadata and notifications for Phoenix projects.</p> </div> <div class="sect4"> <h5 id="_basic_usage"><a class="link" href="#_basic_usage">Basic usage</a></h5> <div class="paragraph"> <p>The primary interface for Phoenix services involves the <code>PhoenixServicesClient</code>, which contains the main methods that interact with the server. Subsequently, using this API usually starts by attaching slots up to the main signals of this interface, then starting interaction.</p> </div> <div class="literalblock"> <div class="content"> <pre>#include <phoenix.h>;</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>using namespace phoenix;</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>PhoenixServicesClient client;</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>// Each client should be tied to a particular Perforce Web Services instance. client.setUrl("http://p4_web_services.mycompany.com");</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>connect(client, &PhoenixServicesClient::logInDone, myObj, &MyObj::logInDone);</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>connect(client, &PhoenixServicesClient::fetchProjectsDone, myObj, &MyObj::fetchProjectsDone);</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>connect(client, &PhoenixServicesClient::fetchProjectDone, myObj, &MyObj::fetchProjectDone);</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>connect(client, &PhoenixServicesClient::createProjectDone, myObj, &MyObj::createProjectDone);</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>client.logIn("myuser", "mypassword");</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void MyObj::logInDone(RequestErrorPtr err, SessionPtr session) { // You should probably check for errors, and probably cache the session // here so you don't have to re-log in</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre> // Load all projects just for a fun starting point client.fetchProjects(); }</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void MyObj::fetchProjectsDone(RequestErrorPtr err, PhoenixProjectListPtr projects) { qDebug() << "I have " << projects->size(); << " projects"; }</pre> </div> </div> <div class="paragraph"> <p>Each PhoenixServicesClient instance requires a Session. A session can be created by calling the <code>PhoenixServicesClient::logIn</code> method, which will then store the session locally. (That Session instance can be stored locally and then, instead of calling `PhoenixServicesClient::logIn, you call PhoenixServicesClient.setSession.) This session will be valid as long as the underlying Perforce server ticket allows. If you start to receive authentication errors, your client will have to log in again, and restore a new session.</p> </div> <div class="paragraph"> <p>Authentication errors are returned with the code <code>RequestError::AUTHENTICATION_ERROR</code> of any <code>RequestError</code> returned by pretty much any server call.</p> </div> </div> <div class="sect4"> <h5 id="__code_phoenixservicesclient_code_reference"><a class="link" href="#__code_phoenixservicesclient_code_reference"><code>PhoenixServicesClient</code> Reference</a></h5> <div class="sect5"> <h6 id="_methods"><a class="link" href="#_methods">Methods</a></h6> <table class="tableblock frame-all grid-all spread"> <colgroup> <col style="width: 50%;"> <col style="width: 50%;"> </colgroup> <thead> <tr> <th class="tableblock halign-left valign-top">Method</th> <th class="tableblock halign-left valign-top">Description</th> </tr> </thead> <tbody> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>bool hasSession() const</code></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">When <code>true</code>, the client has an associated Session object, which it will use on the next slot call to the web server. Does not guarantee that the session has not expired.</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>const QString & phoenixPrefixPath() const</code></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">In some cases, you might have a special prefix where the Phoenix Web Services are deployed on the client, in which case you’d need to configure this path.</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>const Session & session() const</code></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Returns the current Session instance. This might be an empty session that has no actual token values set, if you have not logged in or just set the session directly.</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>void setPhoenixPrefixPath(const QString & path)</code></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Set the prefix path to the Phoenix web services instance. This is typically not needed, unless you mount the services to a different path on the server. Defaults to <code>/p4_phoenix_services/v1</code>.</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>void setSession(const Session & session)</code></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Set the session instance on the client. Really only needs to be done when not using <code>logIn</code> to create the session. If you’re calling <code>logIn</code>, this will be set automatically when successful.</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>void setUrl(const QUrl & url)</code></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Set the Perforce Web Service URL.</p></td> </tr> <tr> <td class="tableblock halign-left valign-top"><p class="tableblock"><code>const QUrl & url() const</code></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">The Perforce web services URL we should connect to. Should be set before making any request.</p></td> </tr> </tbody> </table> <div class="literalblock"> <div class="content"> <pre>Slots</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Slot</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Description</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>createProject(const PhoenixProject &amp; project)</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Requests a new project be created on the server. At the moment, only the name property of the project should be set. The phoenix web services instance will decide other defaults as necessary.</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>fetchProject(const QString &amp; id)</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Requests a single project from the server, based on it's id. This will likely include filtering in the future, when we've defined the workflow better.</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>fetchProjects()</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Requests the complete list of Phoenix projects to the server. This will likely include filtering in the future, when we've defined the workflow better.</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>logIn(const QString &amp; user, const QString &amp; password)</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Will attempt to log in as the user and password to the Perforce web services instance (configured as the URL property of the client). If successful, calls the logInDone signal, and, caches the Session instance locally.</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Signals</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Signal</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Description</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>createProjectDone(RequestErrorPtr error, PhoenixProjectPtr project)</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>When successful, error will be null, and the project should actually be expanded to include any default settings, such as the id, which should generally be a unique string for the project, and the Phoenix extensions on the project model, including the underlying p4d connection URL.</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>fetchProjectDone(RequestErrorPtr error, PhoenixProjectPtr project)</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Called on completion or failure offetchProject(id). If there's any problem, error will not be null, and you should not use theproject.</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>fetchProjectsDone(RequestErrorPtr error, PhoenixProjectListPtr projects)</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Called on completion or failure offetchProjects(). If there's any problem, error will not be null, and you should not use theprojects.</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>void</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>logInDone(RequestErrorPtr error, SessionPtr session)</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>Called on success or failure of the logIn(user, password) slot. If there's any problem, error will not be null, and you should not use thesession.</pre> </div> </div> </div> </div> </div> </div> </div> </div> <div id="footer"> <div id="footer-text"> Version 2015.1.alpha<br> Last updated 2015-05-19 11:12:00 PDT </div> </div> </body> </html>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#69 | 16346 | tjuricek | Removing build directory prior to migration | ||
#68 | 16334 | tjuricek |
HWS/NOARCH/2015.1.main/201510211937 Documentation updates for new system configuration options. |
||
#67 | 16331 | tjuricek |
HWS/NOARCH/2015.1.main/201510211755 This is a large revision to the deployment: - nginx is now part of the system - perforce-server is *not* installed during post-install configuration The only change for migration should be to uninstall (and purge) your current nginx setup. |
||
#66 | 16161 | tjuricek |
HWS/NOARCH/2015.1.main/201510082242 - Ability for custom middleware to filter P4PORT agressively - If p4d deems login not necessary, return an empty string for the valid ticket value. |
||
#65 | 16144 | tjuricek |
HWS/NOARCH/2015.1.main/201510081946 Major revision to URL structure. This is a breaking change to the API. |
||
#64 | 16093 | tjuricek |
HWS/NOARCH/2015.1.main/201510061647 Rename of trust setting, and adjustments to Helix Sync logic for selecting pending changelists |
||
#63 | 16077 | tjuricek |
HWS/NOARCH/2015.1.main/201510051630 Includes changes to trust behavior |
||
#62 | 16007 | tjuricek |
HWS/NOARCH/2015.1.main/201510011648 Documentation updates for the new default parameter to getting the latest helix sync client |
||
#61 | 15975 | tjuricek |
HWS/NOARCH/2015.1.main/201509291925 Add support for repo creation/update and deletion, same for SSH keys. Add util module for supporting methods, modify temp client to dissapear. (Modified submit of review 15549 by @ptomiak) |
||
#60 | 15783 | tjuricek | HWS/NOARCH/2015.1.main/201509180120 | ||
#59 | 15769 | tjuricek | HWS/NOARCH/2015.1.main/201509170120 | ||
#58 | 15758 | tjuricek | HWS/NOARCH/2015.1.main/201509161743 | ||
#57 | 15737 | tjuricek | HWS/NOARCH/2015.1.main/201509150120 | ||
#56 | 15708 | tjuricek | HWS/NOARCH/2015.1.main/201509140120 | ||
#55 | 15699 | tjuricek | HWS/NOARCH/2015.1.main/201509111845 | ||
#54 | 15690 | tjuricek | HWS/NOARCH/2015.1.main/201509110141 | ||
#53 | 15676 | tjuricek | HWS/NOARCH/2015.1.main/201509092205 | ||
#52 | 15545 | tjuricek | Place in config and hooks for Helix Cloud authentication. | ||
#51 | 15530 | tjuricek | Add basic development guide | ||
#50 | 15517 | tjuricek | Do not require changelist ID for submitting Helix Sync pending changelists. | ||
#49 | 15499 | tjuricek | Naive implementation of helix sync project submit for "helix versioning engine projects". | ||
#48 | 15496 | tjuricek |
Revise GET /helix_sync/v1/changes/[project] to /helix_sync/v1/changes/[project]/pending The base method is really intended for the latest changelist number. Meh. |
||
#47 | 15487 | tjuricek | Add basic ability to create pending changelists for helix sync projects. | ||
#46 | 15483 | tjuricek |
Add a new 'hws_console` application to the deployment. This should give users the ability to use the Ruby client for quick and dirty debugging of issues with HWS. Since it's so easy, I've added it to the deployment guide. |
||
#45 | 15479 | tjuricek | Added a basic "HVE project" implementation for creating clients. | ||
#44 | 15460 | tjuricek | Add notes on service startup in deployment | ||
#43 | 15447 | tjuricek |
Add simple Example application to list "projects" in a HVE instance. Qt's a little weird to follow, so I may have to find a different kind of example to write. It does work, however. |
||
#42 | 15435 | tjuricek |
Add proposed HTTP methods for Helix Sync. It's a little unclear to me why you would need a local root directory to create the shared shelving changelist for a particular project (and user). So I didn't add that. |
||
#41 | 15423 | tjuricek |
Revised HWS Qt API. This is a major revision of the API, which removes most of the "typed" data, replacing it with a more generic "executeMethodDone" callback. The main benefit here is to allow the API to interop with different versions of p4d, and not restrict the methods it can call. We may add more helpers in the future. |
||
#40 | 15299 | tjuricek | Revise documentation of our new 'list available services' method. | ||
#39 | 15297 | tjuricek |
Implement of 'cluster services' configuration. The configuration will be stored in a local JSON file, which is expected to be maintained by the systems admin. Eventually, it's expected to have this sort of thing implemented via Helix Admin. |
||
#38 | 15260 | tjuricek |
Fix truncation of content when listing a single file's details. Added message warning people about timeouts. This does work, and doesn't bring the system down, but you'll probably hit timeouts if you're trying to download files using this system. |
||
#37 | 15257 | tjuricek |
Added stress test, corrected per-request header config. Apparently using underscores is a "special" mechanism for HTTP headers, and requires adjusting nginx to allow such things. Might as well just recommend using hyphens, which get converted to underscores anyway. The current test just hits a listing of 20000 files against p4play. Returns a 2.5 MB response, which doesn't seem to cause problems (yay). |
||
#36 | 15242 | tjuricek | Add Helix Sync stubs and documentation | ||
#35 | 15241 | tjuricek | Add Git Fusion stubs and documentation. | ||
#34 | 15240 | tjuricek |
Set api level via request path on all Helix Versioning Engine methods. This will allow migration of applications to different P4D versions. Our internal methods (like project API) should attempt to handle backward compatibility similarly. P4WEBAPI-118 |
||
#33 | 15229 | tjuricek | Remove incorrect default setting for P4HOST | ||
#32 | 15228 | tjuricek | Revise triggers implementation, tests, and documentation. | ||
#31 | 15227 | tjuricek |
Revise implementation, tests, and documentation for protections management. Remove some specs I will not be revising from the helix_web_services project. |
||
#30 | 15225 | tjuricek |
Revise counter implementation, tests, and documentation Wasn't available in the Ruby client before, so, it's now available. |
||
#29 | 15222 | tjuricek |
Revise server specs testing and documentation. Note: also fixed issues with setting P4PORT via headers. For whatever reason, the host setting doesn't seem to work like I expect it to, though P4PORT works just fine. |
||
#28 | 15211 | tjuricek | Implement tests and documentation for label spec management. | ||
#27 | 15210 | tjuricek | Implement tests and documentation for job spec management. | ||
#26 | 15209 | tjuricek | Implement tests and documentation for group spec management. | ||
#25 | 15208 | tjuricek |
Revise 'command' implementation, tests, and documentaiton. This includes a change from a command blacklist to a whitelist. See P4WEBAPI-21 |
||
#24 | 15205 | tjuricek | Implemented tests and documentation for depot spec editing. | ||
#23 | 15189 | tjuricek | Update files implementation, testing, and documentation. | ||
#22 | 15188 | tjuricek | Execute user modification commands as the super user in tests. | ||
#21 | 15185 | tjuricek | Update user spec management implementation, tests, and documentation. | ||
#20 | 15144 | tjuricek |
Setup stream spec tests and documentation. Also revised the documentation folder http_p4_web_api -> helix_versioning_engine |
||
#19 | 15132 | tjuricek | Provde a basic submit -e mechanism on classic perforce workspaces. | ||
#18 | 15110 | tjuricek | Revise changes methods for new p4 connection handling, add server specs, remove model references in client, and update asciidoc documentation. | ||
#17 | 15099 | tjuricek | Revise project services to be our simple 'container' for other systems. | ||
#16 | 15098 | tjuricek |
Revised project services to GET-only forms. With Helix Sync revising to integrate purely with Helix Cloud, this is the only thing we can reasonably define. |
||
#15 | 15090 | tjuricek |
Update _proposed_ API for project services. This is *very likely* to change, and will not be implemented until reviewed. |
||
#14 | 15078 | tjuricek |
clients spec method revisions Updated some other documentation. |
||
#13 | 15077 | tjuricek |
Add new 'model' technique, revised branch spec operations, test Auth::Middleware. The Ruby client now does *not* strictly type anything, but extends OpenStruct with helper methods to help deal with inconsistent data formats. See the OpenModel class documentation for more details. The Auth::Middleware class is also *finally* implemented as well. This does not take into account all possible variations of server behavior (yet), but that will happen in follow-up work. |
||
#12 | 15073 | tjuricek | Update Auth::Middleware and add spec | ||
#11 | 15042 | tjuricek | Document error conventions. | ||
#10 | 15038 | tjuricek | Document 'login' auth method and client programming overview. | ||
#9 | 15032 | tjuricek |
Starting config and doc revisions. System is now broken while revisions underway. Configuration of the p4d connection is now done via a single HWSSettings middleware object injected into the Rack env. The HWSP4Cleanup middleware now cleans up any p4 injected into the Rack env. The Auth::App class now mostly just contains one method to generate a p4 ticket. /auth/v1/login. Added yard documentation for the main project. Yard docs have been reconfigured to dump into build/ directories. This should probably be done with each release. Hm... The top level rake file contains a task, 'all:doc', to update our documentation. This should probably be run for each checkin. Hm... Specs are now using Rack::Test on top of a 'live' p4d. I'd suggest you still use the p4util mechanism, which now dumps to a /tmp folder, so we can safely add P4IGNORE rules back into your local .p4config file. Old 'perforce' application now called 'helix_versioning_engine'. Removing cache data. Helix Sync may be slow. It may also get axed. We'll see. |
||
#8 | 14980 | tjuricek |
Starting to make revisions to the Asciidoc guide. These are just revisions to the preable sections. |
||
#7 | 14184 | tjuricek | Revise the CD diagram, update official docs, and change the DB configuration key. | ||
#6 | 14182 | tjuricek | Asciidoc conversion of the changes HTTP guide | ||
#5 | 14049 | tjuricek |
Add methods to generate client workspaces for a user. The Qt SDK was updated based on immediate need. Also, add Ruby client SDK documentation to the docs site. Everything is early, but there's *some* reference available at least. |
||
#4 | 14027 | tjuricek | Move almost all Qt SDK documentation to Doxygen system, and just reference it in the main doc site. | ||
#3 | 14002 | tjuricek | Some preliminary API documentation for the JavaScript SDK. | ||
#2 | 13614 | tjuricek | Update the Qt guide to include the QSettings* constructor. | ||
#1 | 13612 | tjuricek | Update deployment guide, switch built documentation to asciidoc, remove unused packaging script for p4_web_api |