Showing 4 changed files with 199 additions and 25 deletions
+23
lib/Gitprep/API.pm
... ...
@@ -101,5 +101,28 @@ sub delete_project {
101 101
   my $dbi = $c->app->dbi;
102 102
   $dbi->model('project')->delete(id => [$user, $project]);
103 103
 }
104
+
105
+sub exists_project {
106
+  my ($self, $user, $project) = @_;
107
+
108
+  my $c = $self->cntl;
109
+  my $dbi = $c->app->dbi;
110
+  my $row = $dbi->model('project')->select(id => [$user, $project])->one;
111
+  
112
+  return $row ? 1 : 0;
113
+}
114
+
115
+sub rename_project {
116
+  my ($self, $user, $project, $renamed_project) = @_;
117
+  
118
+  my $c = $self->cntl;
119
+  my $dbi = $c->app->dbi;
120
+  
121
+  croak "Invalid parameters"
122
+    unless defined $user && defined $project && defined $renamed_project;
123
+  
124
+  $dbi->model('project')->update({name => $renamed_project}, id => [$user, $project]);
125
+}
126
+
104 127
 1;
105 128
 
+41 -21
lib/Gitprep/Git.pm
... ...
@@ -341,6 +341,27 @@ sub delete_project {
341 341
   rmtree($rep);
342 342
 }
343 343
 
344
+sub description {
345
+  my ($self, $user, $project, $description) = @_;
346
+  
347
+  my $rep = $self->rep($user, $project);
348
+  my $file = "$rep/description";
349
+  
350
+  if (defined $description) {
351
+    # Write description
352
+    open my $fh, '>',$file
353
+      or croak "Can't open file $rep: $!";
354
+    print $fh encode('UTF-8', $description)
355
+      or croak "Can't write description: $!";
356
+    close $fh;
357
+  }
358
+  else {
359
+    # Read description
360
+    my $description = $self->_slurp($file) || '';
361
+    return $description;
362
+  }
363
+}
364
+
344 365
 sub exists_repository {
345 366
   my ($self, $user, $project) = @_;
346 367
   
... ...
@@ -583,27 +604,6 @@ sub path_by_id {
583 604
   return;
584 605
 }
585 606
 
586
-sub description {
587
-  my ($self, $user, $project, $description) = @_;
588
-  
589
-  my $rep = $self->rep($user, $project);
590
-  my $file = "$rep/description";
591
-  
592
-  if (defined $description) {
593
-    # Write description
594
-    open my $fh, '>',$file
595
-      or croak "Can't open file $rep: $!";
596
-    print $fh encode('UTF-8', $description)
597
-      or croak "Can't write description: $!";
598
-    close $fh;
599
-  }
600
-  else {
601
-    # Read description
602
-    my $description = $self->_slurp($file) || '';
603
-    return $description;
604
-  }
605
-}
606
-
607 607
 sub last_activity {
608 608
   my ($self, $user, $project) = @_;
609 609
   
... ...
@@ -735,6 +735,26 @@ sub references {
735 735
   return \%refs;
736 736
 }
737 737
 
738
+sub rename_project {
739
+  my ($self, $user, $project, $renamed_project) = @_;
740
+  
741
+  croak "Invalid user name or project"
742
+    unless defined $user && defined $project && defined $renamed_project;
743
+  my $rep = $self->rep($user, $project);
744
+  my $renamed_rep = $self->rep($user, $renamed_project);
745
+  
746
+  move($rep, $renamed_rep)
747
+    or croak "Can't move $rep to $renamed_rep: $!";
748
+}
749
+
750
+sub exists_project {
751
+  my ($self, $user, $project) = @_;
752
+  
753
+  my $rep = $self->rep($user, $project);
754
+  
755
+  return -e $rep;
756
+}
757
+
738 758
 sub rep {
739 759
   my ($self, $user, $project) = @_;
740 760
   
+36
lib/Gitprep/RepManager.pm
... ...
@@ -0,0 +1,36 @@
1
+package Gitprep::RepManager;
2
+use Mojo::Base -base;
3
+
4
+has 'c';
5
+
6
+sub rename_project {
7
+  my ($self, $user, $project, $renamed_project) = @_;
8
+  
9
+  my $c = $self->c;
10
+  my $api = $c->gitprep_api($c);
11
+  my $git = $c->app->git;
12
+  my $dbi = $c->app->dbi;
13
+  
14
+  my $error = {};
15
+  
16
+  if ($api->exists_project($user, $renamed_project)
17
+    || $git->exists_project($user, $renamed_project))
18
+  {
19
+    $error->{message} = 'Already exists';
20
+    return $error;
21
+  }
22
+  else {
23
+      $dbi->connector->txn(sub {
24
+        $api->rename_project($user, $project, $renamed_project);
25
+        $git->rename_project($user, $project, $renamed_project);
26
+      });
27
+    if ($@) {
28
+      $error->{message} = 'Rename failed';
29
+      return $error;
30
+    }
31
+  }
32
+  
33
+  return 1;
34
+}
35
+
36
+1;
+99 -4
templates/main/settings.html.ep
... ...
@@ -1,4 +1,6 @@
1 1
 <%
2
+  use Gitprep::RepManager;
3
+
2 4
   my $api = gitprep_api;
3 5
   my $logined = $api->logined;
4 6
   my $user_is_valid = $logined && $user eq session('user_id');
... ...
@@ -9,7 +11,46 @@
9 11
   
10 12
   $api->croak("Fobbiden") if !$user_is_valid;
11 13
   
12
-  if ($op eq 'change_description') {
14
+  if ($op eq 'rename-project') {
15
+  
16
+    # Validation
17
+    my $params = $api->params;
18
+    my $rule = [
19
+      user => [
20
+        'user_name'
21
+      ],
22
+      project => [
23
+        'project_name'
24
+      ],
25
+      'renamed-project' => [
26
+        'project_name'
27
+      ]
28
+    ];
29
+    my $vresult = app->validator->validate($params, $rule);
30
+    
31
+    if ($vresult->is_ok) {
32
+      # Valida parameters
33
+      my $data = $vresult->data;
34
+      my $user = $data->{user};
35
+      my $project = $data->{project};
36
+      my $renamed_project = $data->{'renamed-project'};
37
+      
38
+      # Rename
39
+      my $manager = Gitprep::RepManager->new(c => $self);
40
+      my $error = $manager->rename_project($user, $project, $renamed_project);
41
+      if (ref $error) {
42
+        $self->render(json => {ok => 0, message => $error->{message}});
43
+      }
44
+      else {
45
+        $self->render(json => {ok => 1});
46
+      }
47
+      return $self->res->body;
48
+    }
49
+    else {
50
+      $self->render(json => {ok => 0, message => 'Invalid Parameters'});
51
+    }
52
+  }
53
+  elsif ($op eq 'change_description') {
13 54
     my $description = param('description');
14 55
     $description = '' unless defined $description;
15 56
     
... ...
@@ -60,6 +101,28 @@
60 101
     
61 102
     $(document).ready(function () {
62 103
     
104
+      // Rename project name
105
+      $('#rename').on('click', function () {
106
+        var renamed_project = $('input[name="renamed-project"]').val();
107
+        
108
+        var url = "<%= url_for %>";
109
+        var data = {
110
+          op : "rename-project",
111
+          user: "<%= $user %>",
112
+          project: "<%= $project %>",
113
+          'renamed-project': renamed_project
114
+        };
115
+        $.post(url, data, function (result) {
116
+          if (result.ok) {
117
+            location.href = "<%= url_for("/$user") %>" + '/' + renamed_project;
118
+          }
119
+          else {
120
+            $('#modal-message').text('Rename failed:' + result.message);
121
+            $('#success').modal('show');
122
+          }
123
+        });
124
+      });
125
+      
63 126
       // Change description
64 127
       $('a[href="#description"]').on('click', function () {
65 128
         var description = $('input[name="description"]').val();
... ...
@@ -125,8 +188,10 @@
125 188
       <div class="padding5 border-gray" style="border-top:none">
126 189
         <div >Repository Name</div>
127 190
         <div>
128
-          %= text_field 'project' => $project, style => 'margin-top:9px';
129
-          <a class="btn" href="#rename">Rename</a>
191
+          %= text_field 'renamed-project' => $project, style => 'margin-top:9px';
192
+          <a href="#rename-confirm" role="button" class="btn" data-toggle="modal">
193
+            Rename
194
+          </a>
130 195
         </div>
131 196
       </div>
132 197
       <div class="padding5 border-gray" style="border-top:none">
... ...
@@ -136,6 +201,10 @@
136 201
           %= text_field 'description' => $description, class => 'span8', style => 'margin-top:9px';
137 202
           <a class="btn" href="#description">Save</a>
138 203
         </div>
204
+        <div id="description-success" class="alert alert-success" style="width:150px;display:none">
205
+          <button type="button" class="close" data-dismiss="alert">&times;</button>
206
+          Savaed!
207
+        </div>
139 208
       </div>
140 209
       <div class="border-gray padding5" style="border-top:none">
141 210
         Default Branch
... ...
@@ -168,7 +237,32 @@
168 237
       <button class="btn" data-dismiss="modal" aria-hidden="true">OK</button>
169 238
     </div>
170 239
   </div>
171
-  
240
+
241
+  <div id="rename-confirm" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="rename-confirm-label" aria-hidden="true">
242
+    <div class="modal-header">
243
+      <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
244
+      <div id="modal-message" style="font-weight:bold">Are you sure you want to rename?</div>
245
+    </div>
246
+    <div class="modal-body">
247
+      <p>
248
+        Unexpected bad things will happen if you don't read this
249
+      </p>
250
+      <ul>
251
+        <li>
252
+          We will not set up any redirects from the old location
253
+        </li>
254
+        <li>
255
+          You will need to update your local repositories to point to the new location
256
+        </li>
257
+      </ul>
258
+    </div>
259
+    <div class="modal-footer">
260
+      <button id="rename" class="btn" data-dismiss="modal" aria-hidden="true">
261
+        I understand, rename this repository
262
+      </button>
263
+    </div>
264
+  </div>
265
+
172 266
   <div id="delete-confirm" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="delete-confirm-label" aria-hidden="true">
173 267
     <div class="modal-header">
174 268
       <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
... ...
@@ -194,4 +288,5 @@
194 288
     </div>
195 289
   </div>
196 290
 
291
+
197 292
   %= include '/include/footer';