implement request #13: simple remote forking works now
authorChristian Weiske <cweiske@cweiske.de>
Wed, 19 Sep 2012 21:55:07 +0000 (23:55 +0200)
committerChristian Weiske <cweiske@cweiske.de>
Wed, 19 Sep 2012 21:55:07 +0000 (23:55 +0200)
data/templates/fork-remote-multiple.htm [new file with mode: 0644]
data/templates/fork-remote-new.htm [moved from data/templates/new-fork-remote.htm with 81% similarity]
data/templates/fork-remote.htm
data/templates/new.htm
src/phorkie/ForkRemote.php
www/fork-remote.php

diff --git a/data/templates/fork-remote-multiple.htm b/data/templates/fork-remote-multiple.htm
new file mode 100644 (file)
index 0000000..f5a95b2
--- /dev/null
@@ -0,0 +1,27 @@
+<form method="post" action="/fork-remote" enctype="multipart/form-data" class="well form-inline form-horizontal">
+ <div class="control-group">
+  <p>
+   The URL you provided contains links to several Git repositories.
+   Select one of them.
+  </p>
+  <select size="{{urlselsize}}" name="remote_url" id="sel-remote_url" style="width:100%">
+  {% for grouptitle, groupurls in urls %}
+   {% if groupurls|length == 1 %}
+    <option value="{{groupurls.0}}">{{grouptitle}}</option>
+   {% else %}
+   <optgroup label="{{grouptitle}}">
+    {% for url in groupurls %} 
+    <option value="{{url}}">{{url}}</option>
+    {% endfor %}
+   </optgroup>
+   {% endif %}
+  {% endfor %}
+ </select>
+ </div>
+ <div style="text-align: right">
+  <button type="submit" class="btn btn-primary">
+   <i class="icon-share icon-white"></i> Fork
+  </button>
+ </div>
+
+</form>
\ No newline at end of file
similarity index 81%
rename from data/templates/new-fork-remote.htm
rename to data/templates/fork-remote-new.htm
index 02a94e2..6b48ffe 100644 (file)
@@ -5,8 +5,8 @@
  </p>
 
  <button type="submit" class="btn btn-primary" style="float: right">
-  <i class="icon-share icon-white"></i>Fork remote paste
+  <i class="icon-share icon-white"></i> Fork remote paste
  </button>
  <label for="remote-url">Remote paste URL</label>
- <input type="text" name="remote_url" id="remote-url" value="{{remote_url}}" class="input-xlarge"/>
+ <input type="text" name="remote_url" id="remote-url" value="{{remote_url}}" class="span5"/>
 </form>
index f599ec6..f651661 100644 (file)
@@ -2,5 +2,16 @@
 {% block title %}Fork remote paste{% endblock %}
 
 {% block content %}
- {% include 'new-fork-remote.htm' %}
+ {% include 'fork-remote-new.htm' %}
+
+ {% if error %}
+  <div class="alert alert-error">
+   {{error}}
+  </div>
+ {% endif %}
+
+ {% if urls %}
+  {% include 'fork-remote-multiple.htm' %}
+ {% endif %}
+
 {% endblock %}
index f846fe5..8029b8c 100644 (file)
@@ -21,7 +21,7 @@
 
 </form>
 
-{% include 'new-fork-remote.htm' %}
+{% include 'fork-remote-new.htm' %}
 
 <script type="application/javascript">
 $(document).ready(function() {
index f3639b2..524255a 100644 (file)
@@ -5,6 +5,16 @@ class ForkRemote
 {
     protected $url;
 
+    /**
+     * Array with keys (URL title) and values (arrays of urls)
+     * Only supported URLs are included.
+     *
+     * @var array
+     */
+    protected $arGitUrls;
+
+
+
     public function __construct($url)
     {
         $this->url = $url;
@@ -16,11 +26,11 @@ class ForkRemote
         switch ($scheme) {
         case 'git':
             //clearly a git url
-            $this->gitUrl = $this->url;
+            $this->arGitUrls = array(array($this->url));
             return true;
 
         case 'ssh':
-            //FIXME: maybe loosen this when we know how to skip the 
+            //FIXME: maybe loosen this when we know how to skip the
             //"do you trust this server" question of ssh
             $this->error = 'ssh:// URLs are not supported';
             return false;
@@ -36,6 +46,68 @@ class ForkRemote
 
     protected function extractUrlsFromHtml($url)
     {
+        //HTML is not necessarily well-formed, and Gitorious has many problems
+        // in this regard
+        //$sx = simplexml_load_file($url);
+        libxml_use_internal_errors(true);
+        $sx = simplexml_import_dom(\DomDocument::loadHtmlFile($url));
+        $elems = $sx->xpath('//*[@rel="vcs-git"]');
+
+        $count = $anonymous = 0;
+        foreach ($elems as $elem) {
+            if (!isset($elem['href'])) {
+                continue;
+            }
+            $str = (string)$elem;
+            if (isset($elem['title'])) {
+                //<link href=".." rel="vcs-git" title="title" />
+                $title = (string)$elem['title'];
+            } else if ($str != '') {
+                //<a href=".." rel="vcs-git">title</a>
+                $title = $str;
+            } else {
+                $title = 'Unnamed repository #' . ++$anonymous;
+            }
+            $url = (string)$elem['href'];
+            if ($this->isSupported($url)) {
+                ++$count;
+                $this->arGitUrls[$title][] = $url;
+            }
+        }
+
+        return $count > 0;
+    }
+
+    /**
+     * Iterate through all git urls and return one if there is only
+     * one supported one.
+     *
+     * @return mixed Boolean false or string
+     */
+    public function getUniqueGitUrl()
+    {
+        $nFound = 0;
+        foreach ($this->arGitUrls as $title => $arUrls) {
+            foreach ($arUrls as $url) {
+                $nFound++;
+                $uniqueUrl = $url;
+            }
+        }
+
+        if ($nFound == 1) {
+            return $uniqueUrl;
+        }
+        return false;
+    }
+
+    public function getGitUrls()
+    {
+        return $this->arGitUrls;
+    }
+
+    public function isSupported($url)
+    {
+        return parse_url($url, PHP_URL_SCHEME) == 'git';
     }
 }
 
index dd58165..374c8b8 100644 (file)
@@ -6,19 +6,40 @@ namespace phorkie;
  */
 require_once 'www-header.php';
 
+$error = null;
+$urls  = null;
 if (isset($_POST['remote_url'])) {
     $fr = new ForkRemote($_POST['remote_url']);
-    $fr->parse();
-    if ($fr->hasUniqueGitUrl()) {
-        //FIXME: fork
+    if (false === $fr->parse()) {
+        //no url found
+        $error = 'No git:// clone URL found';
+    } else if (false !== ($gitUrl = $fr->getUniqueGitUrl())) {
+        $forker = new Forker();
+        $new    = $forker->forkRemote($gitUrl);
+        redirect($new->getLink('display'));
+    } else {
+        //multiple urls found
+        $urls = $fr->getGitUrls();
+    }
+}
+
+$selsize = 0;
+if (is_array($urls)) {
+    foreach ($urls as $group) {
+        ++$selsize;
+        if (count($group) > 1) {
+            $selsize += count($group);
+        }
     }
-    //FIXME: display error or selection list
 }
 
 render(
     'fork-remote',
     array(
-        'remote_url' => isset($_POST['remote_url']) ? $_POST['remote_url'] : ''
+        'remote_url' => isset($_POST['remote_url']) ? $_POST['remote_url'] : '',
+        'error'      => $error,
+        'urls'       => $urls,
+        'urlselsize' => $selsize,
     )
 );
 ?>